mirror of
https://github.com/saltstack/salt.git
synced 2025-04-10 23:01:39 +00:00
899 lines
22 KiB
Python
899 lines
22 KiB
Python
"""
|
|
QingCloud Cloud Module
|
|
======================
|
|
|
|
.. versionadded:: 2015.8.0
|
|
|
|
The QingCloud cloud module is used to control access to the QingCloud.
|
|
http://www.qingcloud.com/
|
|
|
|
Use of this module requires the ``access_key_id``, ``secret_access_key``,
|
|
``zone`` and ``key_filename`` parameter to be set.
|
|
|
|
Set up the cloud configuration at ``/etc/salt/cloud.providers`` or
|
|
``/etc/salt/cloud.providers.d/qingcloud.conf``:
|
|
|
|
.. code-block:: yaml
|
|
|
|
my-qingcloud:
|
|
driver: qingcloud
|
|
access_key_id: AKIDMRTGYONNLTFFRBQJ
|
|
secret_access_key: clYwH21U5UOmcov4aNV2V2XocaHCG3JZGcxEczFu
|
|
zone: pek2
|
|
key_filename: /path/to/your.pem
|
|
|
|
:depends: requests
|
|
"""
|
|
|
|
import base64
|
|
import hmac
|
|
import logging
|
|
import pprint
|
|
import time
|
|
import urllib.parse
|
|
from hashlib import sha256
|
|
|
|
import salt.config as config
|
|
import salt.utils.cloud
|
|
import salt.utils.data
|
|
import salt.utils.json
|
|
from salt.exceptions import (
|
|
SaltCloudExecutionFailure,
|
|
SaltCloudExecutionTimeout,
|
|
SaltCloudNotFound,
|
|
SaltCloudSystemExit,
|
|
)
|
|
|
|
try:
|
|
import requests
|
|
|
|
HAS_REQUESTS = True
|
|
except ImportError:
|
|
HAS_REQUESTS = False
|
|
|
|
|
|
# Get logging started
|
|
log = logging.getLogger(__name__)
|
|
|
|
__virtualname__ = "qingcloud"
|
|
|
|
DEFAULT_QINGCLOUD_API_VERSION = 1
|
|
DEFAULT_QINGCLOUD_SIGNATURE_VERSION = 1
|
|
|
|
|
|
# Only load in this module if the qingcloud configurations are in place
|
|
def __virtual__():
|
|
"""
|
|
Check for QingCloud configurations.
|
|
"""
|
|
if get_configured_provider() is False:
|
|
return False
|
|
|
|
if get_dependencies() 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__,
|
|
("access_key_id", "secret_access_key", "zone", "key_filename"),
|
|
)
|
|
|
|
|
|
def get_dependencies():
|
|
"""
|
|
Warn if dependencies aren't met.
|
|
"""
|
|
return config.check_driver_dependencies(__virtualname__, {"requests": HAS_REQUESTS})
|
|
|
|
|
|
def _compute_signature(parameters, access_key_secret, method, path):
|
|
"""
|
|
Generate an API request signature. Detailed document can be found at:
|
|
|
|
https://docs.qingcloud.com/api/common/signature.html
|
|
"""
|
|
parameters["signature_method"] = "HmacSHA256"
|
|
|
|
string_to_sign = f"{method.upper()}\n{path}\n"
|
|
|
|
keys = sorted(parameters.keys())
|
|
pairs = []
|
|
for key in keys:
|
|
val = str(parameters[key]).encode("utf-8")
|
|
pairs.append(
|
|
urllib.parse.quote(key, safe="") + "=" + urllib.parse.quote(val, safe="-_~")
|
|
)
|
|
qs = "&".join(pairs)
|
|
string_to_sign += qs
|
|
|
|
h = hmac.new(access_key_secret, digestmod=sha256)
|
|
h.update(string_to_sign)
|
|
|
|
signature = base64.b64encode(h.digest()).strip()
|
|
|
|
return signature
|
|
|
|
|
|
def query(params=None):
|
|
"""
|
|
Make a web call to QingCloud IaaS API.
|
|
"""
|
|
path = "https://api.qingcloud.com/iaas/"
|
|
|
|
access_key_id = config.get_cloud_config_value(
|
|
"access_key_id", get_configured_provider(), __opts__, search_global=False
|
|
)
|
|
access_key_secret = config.get_cloud_config_value(
|
|
"secret_access_key", get_configured_provider(), __opts__, search_global=False
|
|
)
|
|
|
|
verify_ssl = config.get_cloud_config_value(
|
|
"verify_ssl",
|
|
get_configured_provider(),
|
|
__opts__,
|
|
default=True,
|
|
search_global=False,
|
|
)
|
|
|
|
# public interface parameters
|
|
real_parameters = {
|
|
"access_key_id": access_key_id,
|
|
"signature_version": DEFAULT_QINGCLOUD_SIGNATURE_VERSION,
|
|
"time_stamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
"version": DEFAULT_QINGCLOUD_API_VERSION,
|
|
}
|
|
|
|
# include action or function parameters
|
|
if params:
|
|
for key, value in params.items():
|
|
if isinstance(value, list):
|
|
for i in range(1, len(value) + 1):
|
|
if isinstance(value[i - 1], dict):
|
|
for sk, sv in value[i - 1].items():
|
|
if isinstance(sv, dict) or isinstance(sv, list):
|
|
sv = salt.utils.json.dumps(sv, separators=(",", ":"))
|
|
real_parameters[f"{key}.{i}.{sk}"] = sv
|
|
else:
|
|
real_parameters[f"{key}.{i}"] = value[i - 1]
|
|
else:
|
|
real_parameters[key] = value
|
|
|
|
# Calculate the string for Signature
|
|
signature = _compute_signature(real_parameters, access_key_secret, "GET", "/iaas/")
|
|
real_parameters["signature"] = signature
|
|
|
|
# print('parameters:')
|
|
# pprint.pprint(real_parameters)
|
|
|
|
request = requests.get(path, params=real_parameters, verify=verify_ssl)
|
|
|
|
# print('url:')
|
|
# print(request.url)
|
|
|
|
if request.status_code != 200:
|
|
raise SaltCloudSystemExit(
|
|
"An error occurred while querying QingCloud. HTTP Code: {} "
|
|
"Error: '{}'".format(request.status_code, request.text)
|
|
)
|
|
|
|
log.debug(request.url)
|
|
|
|
content = request.text
|
|
result = salt.utils.json.loads(content)
|
|
|
|
# print('response:')
|
|
# pprint.pprint(result)
|
|
|
|
if result["ret_code"] != 0:
|
|
raise SaltCloudSystemExit(pprint.pformat(result.get("message", {})))
|
|
|
|
return result
|
|
|
|
|
|
def avail_locations(call=None):
|
|
"""
|
|
Return a dict of all available locations on the provider with
|
|
relevant data.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud --list-locations my-qingcloud
|
|
"""
|
|
if call == "action":
|
|
raise SaltCloudSystemExit(
|
|
"The avail_locations function must be called with "
|
|
"-f or --function, or with the --list-locations option"
|
|
)
|
|
|
|
params = {
|
|
"action": "DescribeZones",
|
|
}
|
|
items = query(params=params)
|
|
|
|
result = {}
|
|
for region in items["zone_set"]:
|
|
result[region["zone_id"]] = {}
|
|
for key in region:
|
|
result[region["zone_id"]][key] = str(region[key])
|
|
|
|
return result
|
|
|
|
|
|
def _get_location(vm_=None):
|
|
"""
|
|
Return the VM's location. Used by create().
|
|
"""
|
|
locations = avail_locations()
|
|
|
|
vm_location = str(
|
|
config.get_cloud_config_value("zone", vm_, __opts__, search_global=False)
|
|
)
|
|
|
|
if not vm_location:
|
|
raise SaltCloudNotFound("No location specified for this VM.")
|
|
|
|
if vm_location in locations:
|
|
return vm_location
|
|
|
|
raise SaltCloudNotFound(
|
|
f"The specified location, '{vm_location}', could not be found."
|
|
)
|
|
|
|
|
|
def _get_specified_zone(kwargs=None, provider=None):
|
|
if provider is None:
|
|
provider = get_configured_provider()
|
|
|
|
if isinstance(kwargs, dict):
|
|
zone = kwargs.get("zone", None)
|
|
if zone is not None:
|
|
return zone
|
|
|
|
zone = provider["zone"]
|
|
return zone
|
|
|
|
|
|
def avail_images(kwargs=None, call=None):
|
|
"""
|
|
Return a list of the images that are on the provider.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud --list-images my-qingcloud
|
|
salt-cloud -f avail_images my-qingcloud zone=gd1
|
|
"""
|
|
if call == "action":
|
|
raise SaltCloudSystemExit(
|
|
"The avail_images function must be called with "
|
|
"-f or --function, or with the --list-images option"
|
|
)
|
|
|
|
if not isinstance(kwargs, dict):
|
|
kwargs = {}
|
|
|
|
params = {
|
|
"action": "DescribeImages",
|
|
"provider": "system",
|
|
"zone": _get_specified_zone(kwargs, get_configured_provider()),
|
|
}
|
|
items = query(params=params)
|
|
|
|
result = {}
|
|
for image in items["image_set"]:
|
|
result[image["image_id"]] = {}
|
|
for key in image:
|
|
result[image["image_id"]][key] = image[key]
|
|
|
|
return result
|
|
|
|
|
|
def _get_image(vm_):
|
|
"""
|
|
Return the VM's image. Used by create().
|
|
"""
|
|
images = avail_images()
|
|
vm_image = str(
|
|
config.get_cloud_config_value("image", vm_, __opts__, search_global=False)
|
|
)
|
|
|
|
if not vm_image:
|
|
raise SaltCloudNotFound("No image specified for this VM.")
|
|
|
|
if vm_image in images:
|
|
return vm_image
|
|
|
|
raise SaltCloudNotFound(f"The specified image, '{vm_image}', could not be found.")
|
|
|
|
|
|
def show_image(kwargs, call=None):
|
|
"""
|
|
Show the details from QingCloud concerning an image.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -f show_image my-qingcloud image=trustysrvx64c
|
|
salt-cloud -f show_image my-qingcloud image=trustysrvx64c,coreos4
|
|
salt-cloud -f show_image my-qingcloud image=trustysrvx64c zone=ap1
|
|
"""
|
|
if call != "function":
|
|
raise SaltCloudSystemExit(
|
|
"The show_images function must be called with -f or --function"
|
|
)
|
|
|
|
if not isinstance(kwargs, dict):
|
|
kwargs = {}
|
|
|
|
images = kwargs["image"]
|
|
images = images.split(",")
|
|
|
|
params = {
|
|
"action": "DescribeImages",
|
|
"images": images,
|
|
"zone": _get_specified_zone(kwargs, get_configured_provider()),
|
|
}
|
|
|
|
items = query(params=params)
|
|
|
|
if not items["image_set"]:
|
|
raise SaltCloudNotFound("The specified image could not be found.")
|
|
|
|
result = {}
|
|
for image in items["image_set"]:
|
|
result[image["image_id"]] = {}
|
|
for key in image:
|
|
result[image["image_id"]][key] = image[key]
|
|
|
|
return result
|
|
|
|
|
|
# QingCloud doesn't provide an API of geting instance sizes
|
|
QINGCLOUD_SIZES = {
|
|
"pek2": {
|
|
"c1m1": {"cpu": 1, "memory": "1G"},
|
|
"c1m2": {"cpu": 1, "memory": "2G"},
|
|
"c1m4": {"cpu": 1, "memory": "4G"},
|
|
"c2m2": {"cpu": 2, "memory": "2G"},
|
|
"c2m4": {"cpu": 2, "memory": "4G"},
|
|
"c2m8": {"cpu": 2, "memory": "8G"},
|
|
"c4m4": {"cpu": 4, "memory": "4G"},
|
|
"c4m8": {"cpu": 4, "memory": "8G"},
|
|
"c4m16": {"cpu": 4, "memory": "16G"},
|
|
},
|
|
"pek1": {
|
|
"small_b": {"cpu": 1, "memory": "1G"},
|
|
"small_c": {"cpu": 1, "memory": "2G"},
|
|
"medium_a": {"cpu": 2, "memory": "2G"},
|
|
"medium_b": {"cpu": 2, "memory": "4G"},
|
|
"medium_c": {"cpu": 2, "memory": "8G"},
|
|
"large_a": {"cpu": 4, "memory": "4G"},
|
|
"large_b": {"cpu": 4, "memory": "8G"},
|
|
"large_c": {"cpu": 4, "memory": "16G"},
|
|
},
|
|
}
|
|
QINGCLOUD_SIZES["ap1"] = QINGCLOUD_SIZES["pek2"]
|
|
QINGCLOUD_SIZES["gd1"] = QINGCLOUD_SIZES["pek2"]
|
|
|
|
|
|
def avail_sizes(kwargs=None, call=None):
|
|
"""
|
|
Return a list of the instance sizes that are on the provider.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud --list-sizes my-qingcloud
|
|
salt-cloud -f avail_sizes my-qingcloud zone=pek2
|
|
"""
|
|
if call == "action":
|
|
raise SaltCloudSystemExit(
|
|
"The avail_sizes function must be called with "
|
|
"-f or --function, or with the --list-sizes option"
|
|
)
|
|
|
|
zone = _get_specified_zone(kwargs, get_configured_provider())
|
|
|
|
result = {}
|
|
for size_key in QINGCLOUD_SIZES[zone]:
|
|
result[size_key] = {}
|
|
for attribute_key in QINGCLOUD_SIZES[zone][size_key]:
|
|
result[size_key][attribute_key] = QINGCLOUD_SIZES[zone][size_key][
|
|
attribute_key
|
|
]
|
|
|
|
return result
|
|
|
|
|
|
def _get_size(vm_):
|
|
"""
|
|
Return the VM's size. Used by create().
|
|
"""
|
|
sizes = avail_sizes()
|
|
|
|
vm_size = str(
|
|
config.get_cloud_config_value("size", vm_, __opts__, search_global=False)
|
|
)
|
|
|
|
if not vm_size:
|
|
raise SaltCloudNotFound("No size specified for this instance.")
|
|
|
|
if vm_size in sizes.keys():
|
|
return vm_size
|
|
|
|
raise SaltCloudNotFound(f"The specified size, '{vm_size}', could not be found.")
|
|
|
|
|
|
def _show_normalized_node(full_node):
|
|
"""
|
|
Normalize the QingCloud instance data. Used by list_nodes()-related
|
|
functions.
|
|
"""
|
|
public_ips = full_node.get("eip", [])
|
|
if public_ips:
|
|
public_ip = public_ips["eip_addr"]
|
|
public_ips = [
|
|
public_ip,
|
|
]
|
|
|
|
private_ips = []
|
|
for vxnet in full_node.get("vxnets", []):
|
|
private_ip = vxnet.get("private_ip", None)
|
|
if private_ip:
|
|
private_ips.append(private_ip)
|
|
|
|
normalized_node = {
|
|
"id": full_node["instance_id"],
|
|
"image": full_node["image"]["image_id"],
|
|
"size": full_node["instance_type"],
|
|
"state": full_node["status"],
|
|
"private_ips": private_ips,
|
|
"public_ips": public_ips,
|
|
}
|
|
|
|
return normalized_node
|
|
|
|
|
|
def list_nodes_full(call=None):
|
|
"""
|
|
Return a list of the instances that are on the provider.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -F my-qingcloud
|
|
"""
|
|
if call == "action":
|
|
raise SaltCloudSystemExit(
|
|
"The list_nodes_full function must be called with -f or --function."
|
|
)
|
|
|
|
zone = _get_specified_zone()
|
|
|
|
params = {
|
|
"action": "DescribeInstances",
|
|
"zone": zone,
|
|
"status": ["pending", "running", "stopped", "suspended"],
|
|
}
|
|
items = query(params=params)
|
|
|
|
log.debug("Total %s instances found in zone %s", items["total_count"], zone)
|
|
|
|
result = {}
|
|
|
|
if items["total_count"] == 0:
|
|
return result
|
|
|
|
for node in items["instance_set"]:
|
|
normalized_node = _show_normalized_node(node)
|
|
node.update(normalized_node)
|
|
|
|
result[node["instance_id"]] = node
|
|
|
|
provider = _get_active_provider_name() or "qingcloud"
|
|
if ":" in provider:
|
|
comps = provider.split(":")
|
|
provider = comps[0]
|
|
|
|
__opts__["update_cachedir"] = True
|
|
__utils__["cloud.cache_node_list"](result, provider, __opts__)
|
|
|
|
return result
|
|
|
|
|
|
def list_nodes(call=None):
|
|
"""
|
|
Return a list of the instances that are on the provider.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -Q my-qingcloud
|
|
"""
|
|
if call == "action":
|
|
raise SaltCloudSystemExit(
|
|
"The list_nodes function must be called with -f or --function."
|
|
)
|
|
|
|
nodes = list_nodes_full()
|
|
|
|
ret = {}
|
|
for instance_id, full_node in nodes.items():
|
|
ret[instance_id] = {
|
|
"id": full_node["id"],
|
|
"image": full_node["image"],
|
|
"size": full_node["size"],
|
|
"state": full_node["state"],
|
|
"public_ips": full_node["public_ips"],
|
|
"private_ips": full_node["private_ips"],
|
|
}
|
|
|
|
return ret
|
|
|
|
|
|
def list_nodes_min(call=None):
|
|
"""
|
|
Return a list of the instances that are on the provider. Only a list of
|
|
instances names, and their state, is returned.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -f list_nodes_min my-qingcloud
|
|
"""
|
|
if call != "function":
|
|
raise SaltCloudSystemExit(
|
|
"The list_nodes_min function must be called with -f or --function."
|
|
)
|
|
|
|
nodes = list_nodes_full()
|
|
|
|
result = {}
|
|
for instance_id, full_node in nodes.items():
|
|
result[instance_id] = {
|
|
"name": full_node["instance_name"],
|
|
"status": full_node["status"],
|
|
}
|
|
|
|
return result
|
|
|
|
|
|
def list_nodes_select(call=None):
|
|
"""
|
|
Return a list of the instances that are on the provider, with selected
|
|
fields.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -S my-qingcloud
|
|
"""
|
|
return salt.utils.cloud.list_nodes_select(
|
|
list_nodes_full("function"),
|
|
__opts__["query.selection"],
|
|
call,
|
|
)
|
|
|
|
|
|
def show_instance(instance_id, call=None, kwargs=None):
|
|
"""
|
|
Show the details from QingCloud concerning an instance.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -a show_instance i-2f733r5n
|
|
"""
|
|
if call != "action":
|
|
raise SaltCloudSystemExit(
|
|
"The show_instance action must be called with -a or --action."
|
|
)
|
|
|
|
params = {
|
|
"action": "DescribeInstances",
|
|
"instances.1": instance_id,
|
|
"zone": _get_specified_zone(kwargs=None, provider=get_configured_provider()),
|
|
}
|
|
items = query(params=params)
|
|
|
|
if items["total_count"] == 0:
|
|
raise SaltCloudNotFound(
|
|
f"The specified instance, '{instance_id}', could not be found."
|
|
)
|
|
|
|
full_node = items["instance_set"][0]
|
|
normalized_node = _show_normalized_node(full_node)
|
|
full_node.update(normalized_node)
|
|
|
|
result = full_node
|
|
|
|
return result
|
|
|
|
|
|
def _query_node_data(instance_id):
|
|
data = show_instance(instance_id, call="action")
|
|
|
|
if not data:
|
|
return False
|
|
|
|
if data.get("private_ips", []):
|
|
return data
|
|
|
|
|
|
def create(vm_):
|
|
"""
|
|
Create a single instance from a data dict.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -p qingcloud-ubuntu-c1m1 hostname1
|
|
salt-cloud -m /path/to/mymap.sls -P
|
|
"""
|
|
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 "qingcloud",
|
|
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"],
|
|
)
|
|
|
|
log.info("Creating Cloud VM %s", vm_["name"])
|
|
|
|
# params
|
|
params = {
|
|
"action": "RunInstances",
|
|
"instance_name": vm_["name"],
|
|
"zone": _get_location(vm_),
|
|
"instance_type": _get_size(vm_),
|
|
"image_id": _get_image(vm_),
|
|
"vxnets.1": vm_["vxnets"],
|
|
"login_mode": vm_["login_mode"],
|
|
"login_keypair": vm_["login_keypair"],
|
|
}
|
|
|
|
__utils__["cloud.fire_event"](
|
|
"event",
|
|
"requesting instance",
|
|
"salt/cloud/{}/requesting".format(vm_["name"]),
|
|
args={
|
|
"kwargs": __utils__["cloud.filter_event"](
|
|
"requesting", params, list(params)
|
|
),
|
|
},
|
|
sock_dir=__opts__["sock_dir"],
|
|
transport=__opts__["transport"],
|
|
)
|
|
|
|
result = query(params)
|
|
new_instance_id = result["instances"][0]
|
|
|
|
try:
|
|
data = salt.utils.cloud.wait_for_ip(
|
|
_query_node_data,
|
|
update_args=(new_instance_id,),
|
|
timeout=config.get_cloud_config_value(
|
|
"wait_for_ip_timeout", vm_, __opts__, default=10 * 60
|
|
),
|
|
interval=config.get_cloud_config_value(
|
|
"wait_for_ip_interval", vm_, __opts__, default=10
|
|
),
|
|
)
|
|
except (SaltCloudExecutionTimeout, SaltCloudExecutionFailure) as exc:
|
|
try:
|
|
# It might be already up, let's destroy it!
|
|
destroy(vm_["name"])
|
|
except SaltCloudSystemExit:
|
|
pass
|
|
finally:
|
|
raise SaltCloudSystemExit(str(exc))
|
|
|
|
private_ip = data["private_ips"][0]
|
|
|
|
log.debug("VM %s is now running", private_ip)
|
|
|
|
vm_["ssh_host"] = private_ip
|
|
|
|
# The instance is booted and accessible, let's Salt it!
|
|
__utils__["cloud.bootstrap"](vm_, __opts__)
|
|
|
|
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 data
|
|
|
|
|
|
def script(vm_):
|
|
"""
|
|
Return the script deployment object.
|
|
"""
|
|
deploy_script = salt.utils.cloud.os_script(
|
|
config.get_cloud_config_value("script", vm_, __opts__),
|
|
vm_,
|
|
__opts__,
|
|
salt.utils.cloud.salt_config_to_yaml(
|
|
salt.utils.cloud.minion_config(__opts__, vm_)
|
|
),
|
|
)
|
|
|
|
return deploy_script
|
|
|
|
|
|
def start(instance_id, call=None):
|
|
"""
|
|
Start an instance.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -a start i-2f733r5n
|
|
"""
|
|
if call != "action":
|
|
raise SaltCloudSystemExit("The stop action must be called with -a or --action.")
|
|
|
|
log.info("Starting instance %s", instance_id)
|
|
|
|
params = {
|
|
"action": "StartInstances",
|
|
"zone": _get_specified_zone(provider=get_configured_provider()),
|
|
"instances.1": instance_id,
|
|
}
|
|
result = query(params)
|
|
|
|
return result
|
|
|
|
|
|
def stop(instance_id, force=False, call=None):
|
|
"""
|
|
Stop an instance.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -a stop i-2f733r5n
|
|
salt-cloud -a stop i-2f733r5n force=True
|
|
"""
|
|
if call != "action":
|
|
raise SaltCloudSystemExit("The stop action must be called with -a or --action.")
|
|
|
|
log.info("Stopping instance %s", instance_id)
|
|
|
|
params = {
|
|
"action": "StopInstances",
|
|
"zone": _get_specified_zone(provider=get_configured_provider()),
|
|
"instances.1": instance_id,
|
|
"force": int(force),
|
|
}
|
|
result = query(params)
|
|
|
|
return result
|
|
|
|
|
|
def reboot(instance_id, call=None):
|
|
"""
|
|
Reboot an instance.
|
|
|
|
CLI Examples:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -a reboot i-2f733r5n
|
|
"""
|
|
if call != "action":
|
|
raise SaltCloudSystemExit("The stop action must be called with -a or --action.")
|
|
|
|
log.info("Rebooting instance %s", instance_id)
|
|
|
|
params = {
|
|
"action": "RestartInstances",
|
|
"zone": _get_specified_zone(provider=get_configured_provider()),
|
|
"instances.1": instance_id,
|
|
}
|
|
result = query(params)
|
|
|
|
return result
|
|
|
|
|
|
def destroy(instance_id, call=None):
|
|
"""
|
|
Destroy an instance.
|
|
|
|
CLI Example:
|
|
|
|
.. code-block:: bash
|
|
|
|
salt-cloud -a destroy i-2f733r5n
|
|
salt-cloud -d i-2f733r5n
|
|
"""
|
|
if call == "function":
|
|
raise SaltCloudSystemExit(
|
|
"The destroy action must be called with -d, --destroy, -a or --action."
|
|
)
|
|
|
|
instance_data = show_instance(instance_id, call="action")
|
|
name = instance_data["instance_name"]
|
|
|
|
__utils__["cloud.fire_event"](
|
|
"event",
|
|
"destroying instance",
|
|
f"salt/cloud/{name}/destroying",
|
|
args={"name": name},
|
|
sock_dir=__opts__["sock_dir"],
|
|
transport=__opts__["transport"],
|
|
)
|
|
|
|
params = {
|
|
"action": "TerminateInstances",
|
|
"zone": _get_specified_zone(provider=get_configured_provider()),
|
|
"instances.1": instance_id,
|
|
}
|
|
result = query(params)
|
|
|
|
__utils__["cloud.fire_event"](
|
|
"event",
|
|
"destroyed instance",
|
|
f"salt/cloud/{name}/destroyed",
|
|
args={"name": name},
|
|
sock_dir=__opts__["sock_dir"],
|
|
transport=__opts__["transport"],
|
|
)
|
|
|
|
return result
|