1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Stub out modules scheduled for 2.8 removal (#44985)

* Remove modules scheduled for 2.8

* Add changelog and porting guide

* Skip docs test on removed modules

* Don't link to removed modules
This commit is contained in:
Matt Martz 2018-08-31 16:27:32 -05:00 committed by GitHub
parent b64e666643
commit f89d873698
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 98 additions and 1485 deletions

View file

@ -0,0 +1,6 @@
removed_features:
- ec2_remote_facts - deprecated module removed (https://github.com/ansible/ansible/pull/44985)
- azure - deprecated module removed (https://github.com/ansible/ansible/pull/44985)
- cs_nic - deprecated module removed (https://github.com/ansible/ansible/pull/44985)
- netscaler - deprecated module removed (https://github.com/ansible/ansible/pull/44985)
- win_msi - deprecated module removed (https://github.com/ansible/ansible/pull/44985)

View file

@ -91,8 +91,8 @@ Deprecation notices
The following modules will be removed in Ansible 2.8. Please update your playbooks accordingly. The following modules will be removed in Ansible 2.8. Please update your playbooks accordingly.
* :ref:`azure <azure_module>`, use :ref:`azure_rm_virtualmachine <azure_rm_virtualmachine_module>`, which uses the new Resource Manager SDK. * azure, use :ref:`azure_rm_virtualmachine <azure_rm_virtualmachine_module>`, which uses the new Resource Manager SDK.
* :ref:`win_msi <win_msi_module>`, use :ref:`win_package <win_package_module>` instead * win_msi, use :ref:`win_package <win_package_module>` instead
Noteworthy module changes Noteworthy module changes
------------------------- -------------------------

View file

@ -0,0 +1,68 @@
.. _porting_2.8_guide:
*************************
Ansible 2.8 Porting Guide
*************************
This section discusses the behavioral changes between Ansible 2.7 and Ansible 2.8.
It is intended to assist in updating your playbooks, plugins and other parts of your Ansible infrastructure so they will work with this version of Ansible.
We suggest you read this page along with `Ansible Changelog for 2.8 <https://github.com/ansible/ansible/blob/devel/changelogs/CHANGELOG-v2.8.rst>`_ to understand what updates you may need to make.
This document is part of a collection on porting. The complete list of porting guides can be found at :ref:`porting guides <porting_guides>`.
.. contents:: Topics
Playbook
========
No notable changes.
Deprecated
==========
No notable changes.
Modules
=======
Major changes in popular modules are detailed here
Modules removed
---------------
The following modules no longer exist:
* ec2_remote_facts
* azure
* cs_nic
* netscaler
* win_msi
Deprecation notices
-------------------
The following modules will be removed in Ansible 2.12. Please update your playbooks accordingly.
Noteworthy module changes
-------------------------
Plugins
=======
No notable changes.
Porting custom scripts
======================
No notable changes.
Networking
==========
No notable changes.

View file

@ -17,3 +17,4 @@ Please note that this is not a complete list. If you believe any extra informati
porting_guide_2.5 porting_guide_2.5
porting_guide_2.6 porting_guide_2.6
porting_guide_2.7 porting_guide_2.7
porting_guide_2.8

View file

@ -7,400 +7,12 @@ __metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['deprecated'], 'status': ['removed'],
'supported_by': 'certified'} 'supported_by': 'certified'}
DOCUMENTATION = ''' from ansible.module_utils.common.removed import removed_module
---
module: ec2_remote_facts
short_description: Gather facts about ec2 instances in AWS
deprecated:
removed_in: "2.8"
why: Replaced with boto3 version.
alternative: Use M(ec2_instance_facts) instead.
description:
- Gather facts about ec2 instances in AWS
version_added: "2.0"
options:
filters:
description:
- A dict of filters to apply. Each dict item consists of a filter key and a filter value.
See U(http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html) for possible filters.
author:
- "Michael Schuett (@michaeljs1990)"
extends_documentation_fragment:
- aws
- ec2
'''
EXAMPLES = '''
# Note: These examples do not set authentication details, see the AWS Guide for details.
# Gather facts about all ec2 instances
- ec2_remote_facts:
# Gather facts about all running ec2 instances with a tag of Name:Example
- ec2_remote_facts:
filters:
instance-state-name: running
"tag:Name": Example
# Gather facts about instance i-123456
- ec2_remote_facts:
filters:
instance-id: i-123456
# Gather facts about all instances in vpc-123456 that are t2.small type
- ec2_remote_facts:
filters:
vpc-id: vpc-123456
instance-type: t2.small
'''
RETURN = '''
instances:
description: provides details about EC2 instance(s) found in AWS region
returned: when EC2 instances are found in AWS region otherwise empty
type: complex
contains:
ami_launch_index:
description: >
if more than one instance is started at the same time, this value indicates the order in which the instance was launched,
the value of the first instance launched is 0
returned: success
type: string
sample: "0"
architecture:
description: the instance architecture
returned: success
type: string
sample: "x86_64"
block_device_mapping:
description: a structure describing the attached volumes to instance
returned: success
type: complex
contains:
attach_time:
description: the attach time for an EBS volume mapped to the instance
returned: success
type: string
sample: "2017-01-03T15:19:52.000Z"
delete_on_termination:
description: indicates whether the EBS volume is deleted on instance termination
returned: success
type: boolean
sample: "true"
device_name:
description: the device name for the EBS volume
returned: success
type: string
sample: "/dev/sda1"
status:
description: the status for the EBS volume
returned: success
type: string
sample: "attaching"
volume_id:
description: the volume id of the EBS volume
returned: success
type: string
sample: "vol-3160f90df06b24080"
client_token:
description: the idempotency token provided when instance was launched
returned: success
type: string
sample: "Sample-awsmp-DFNBSML8ZMJ9"
ebs_optimized:
description: whether instance class has EBS optimized flag turned on
returned: success
type: boolean
sample: "true"
groups:
description: a list security groups to which the network interface belongs
returned: success
type: complex
contains:
id:
description: security group id
returned: success
type: string
sample: "sg-e203cf94"
name:
descriptipn: security group name
returned: success
type: string
sample: "Sample-Common-Sg"
hypervisor:
description: the hypervisor type of the instance
returned: success
type: string
sample: "xen"
id:
description: the id of the instance
returned: success
type: string
sample: "i-09275d68c04c1a16c"
image_id:
description: the id of the image used to launch the instance
returned: success
type: string
sample: "ami-1748d2f5"
instance_profile:
description: the instance profile associated with the instance
returned: success
type: complex
contains:
arn:
description: specifies an ARN of instance profile
returned: success
type: string
sample: "arn:aws:iam::171455704129:instance-profile/Sample-IamProfile"
id:
description: instance profile id
returned: success
type: string
sample: "AIPAD5WIZGNR9TH6LBFE4"
interfaces:
description: a list of ENI associated to instance
returned: success
type: complex
contains:
id:
description: the id of ENI
returned: success
type: string
sample: "eni-cf96b081"
mac_address:
description: the MAC address of ENI
returned: success
type: string
sample: "06:c4:fd:90:dc:61"
kernel:
description: the kernel id
returned: success
type: string
sample: "null"
key_name:
description: the name of the key pair used when the instance was launched
returned: success
type: string
sample: "MyKey"
launch_time":
description: the time when the instance was launched
returned: success
type: string
sample: "2017-06-16T15:44:54.000Z"
monitoring_state:
description: indicates whether detailed monitoring is enabled
returned: success
type: string
sample: "disabled"
private_dns_name:
description: the private IPv4 DNS name of the instance
returned: success
type: string
sample: "ip-10-21-39-23.ag-net.com"
private_ip_address:
description: the private IPv4 address of the instance
returned: success
type: string
sample: "10.216.139.23"
public_dns_name:
description: the public DNS name of the instance
returned: success
type: string
sample: "ec2-54-194-252-215.eu-west-1.compute.amazonaws.com"
public_ip_address:
description: the public IPv4 address of the instance
returned: success
type: string
sample: "54.194.252.215"
ramdisk:
description: the RAM disk id
returned: success
type: string
sample: "null"
region:
description: the AWS region in which instance is running in
returned: success
type: string
sample: "eu-west-1"
requester_id:
description: the id of the entity that launched the instance on your behalf
returned: success
type: string
sample: "null"
root_device_type:
description: the type of root device that the instance uses
returned: success
type: string
sample: "ebs"
source_destination_check:
description: indicates whether the instance performs source/destination checking
returned: success
type: boolean
sample: "true"
spot_instance_request_id:
description: the id of the spot instance request
returned: success
type: string
sample: "null"
state:
description: a message that describes the state change
returned: success
type: string
sample: "running"
tags:
description: a dictionary of key/value pairs assigned to the resource
returned: success
type: complex
contains:
key:
description: the key of a tag assigned to the resource
returned: success
type: string
sample: "Environment"
virtualization_type:
description: the virtualization type of the instance
returned: success
type: string
sample: "hvm"
vpc_id:
description: the id of the VPC that the instance is running in
returned: success
type: string
sample: "vpc-12c9ae4f"
'''
try:
import boto.ec2
from boto.exception import BotoServerError
HAS_BOTO = True
except ImportError:
HAS_BOTO = False
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ec2 import AnsibleAWSError, connect_to_aws, ec2_argument_spec, get_aws_connection_info
def get_instance_info(instance):
# Get groups
groups = []
for group in instance.groups:
groups.append({'id': group.id, 'name': group.name}.copy())
# Get interfaces
interfaces = []
for interface in instance.interfaces:
interfaces.append({'id': interface.id, 'mac_address': interface.mac_address}.copy())
# If an instance is terminated, sourceDestCheck is no longer returned
try:
source_dest_check = instance.sourceDestCheck
except AttributeError:
source_dest_check = None
# Get block device mapping
try:
bdm_dict = []
bdm = getattr(instance, 'block_device_mapping')
for device_name in bdm.keys():
bdm_dict.append({
'device_name': device_name,
'status': bdm[device_name].status,
'volume_id': bdm[device_name].volume_id,
'delete_on_termination': bdm[device_name].delete_on_termination,
'attach_time': bdm[device_name].attach_time
})
except AttributeError:
pass
instance_profile = dict(instance.instance_profile) if instance.instance_profile is not None else None
instance_info = {'id': instance.id,
'kernel': instance.kernel,
'instance_profile': instance_profile,
'root_device_type': instance.root_device_type,
'private_dns_name': instance.private_dns_name,
'public_dns_name': instance.public_dns_name,
'ebs_optimized': instance.ebs_optimized,
'client_token': instance.client_token,
'virtualization_type': instance.virtualization_type,
'architecture': instance.architecture,
'ramdisk': instance.ramdisk,
'tags': instance.tags,
'key_name': instance.key_name,
'source_destination_check': source_dest_check,
'image_id': instance.image_id,
'groups': groups,
'interfaces': interfaces,
'spot_instance_request_id': instance.spot_instance_request_id,
'requester_id': instance.requester_id,
'monitoring_state': instance.monitoring_state,
'placement': {
'tenancy': instance._placement.tenancy,
'zone': instance._placement.zone
},
'ami_launch_index': instance.ami_launch_index,
'launch_time': instance.launch_time,
'hypervisor': instance.hypervisor,
'region': instance.region.name,
'persistent': instance.persistent,
'private_ip_address': instance.private_ip_address,
'public_ip_address': instance.ip_address,
'state': instance._state.name,
'vpc_id': instance.vpc_id,
'block_device_mapping': bdm_dict,
}
return instance_info
def list_ec2_instances(connection, module):
filters = module.params.get("filters")
instance_dict_array = []
try:
all_instances = connection.get_only_instances(filters=filters)
except BotoServerError as e:
module.fail_json(msg=e.message)
for instance in all_instances:
instance_dict_array.append(get_instance_info(instance))
module.exit_json(instances=instance_dict_array)
def main():
argument_spec = ec2_argument_spec()
argument_spec.update(
dict(
filters=dict(default=None, type='dict')
)
)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
if not HAS_BOTO:
module.fail_json(msg='boto required for this module')
region, ec2_url, aws_connect_params = get_aws_connection_info(module)
if region:
try:
connection = connect_to_aws(boto.ec2, region, **aws_connect_params)
except (boto.exception.NoAuthHandlerFound, AnsibleAWSError) as e:
module.fail_json(msg=str(e))
else:
module.fail_json(msg="region must be specified")
list_ec2_instances(connection, module)
if __name__ == '__main__': if __name__ == '__main__':
main() removed_module(removed_in='2.8')

View file

@ -8,590 +8,12 @@ __metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['deprecated'], 'status': ['removed'],
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = ''' from ansible.module_utils.common.removed import removed_module
---
module: azure
short_description: create or terminate a virtual machine in azure
description:
- Creates or terminates azure instances. When created optionally waits for it to be 'running'.
version_added: "1.7"
deprecated:
removed_in: "2.8"
why: Replaced with various dedicated Azure modules.
alternative: M(azure_rm_virtualmachine)
options:
name:
description:
- name of the virtual machine and associated cloud service.
required: true
location:
description:
- the azure location to use (e.g. 'East US')
required: true
subscription_id:
description:
- azure subscription id. Overrides the AZURE_SUBSCRIPTION_ID environment variable.
management_cert_path:
description:
- path to an azure management certificate associated with the subscription id. Overrides the AZURE_CERT_PATH environment variable.
storage_account:
description:
- the azure storage account in which to store the data disks.
required: true
image:
description:
- system image for creating the virtual machine
(e.g., b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-precise-12_04_3-LTS-amd64-server-20131205-en-us-30GB)
required: true
role_size:
description:
- azure role size for the new virtual machine (e.g., Small, ExtraLarge, A6). You have to pay attention to the fact that instances of
type G and DS are not available in all regions (locations). Make sure if you selected the size and type of instance available in your chosen location.
default: Small
endpoints:
description:
- a comma-separated list of TCP ports to expose on the virtual machine (e.g., "22,80")
default: 22
user:
description:
- the unix username for the new virtual machine.
password:
description:
- the unix password for the new virtual machine.
ssh_cert_path:
description:
- path to an X509 certificate containing the public ssh key to install in the virtual machine.
See http://www.windowsazure.com/en-us/manage/linux/tutorials/intro-to-linux/ for more details.
- if this option is specified, password-based ssh authentication will be disabled.
virtual_network_name:
description:
- Name of virtual network.
hostname:
description:
- hostname to write /etc/hostname. Defaults to <name>.cloudapp.net.
wait:
description:
- wait for the instance to be in state 'running' before returning
type: bool
default: 'no'
wait_timeout:
description:
- how long before wait gives up, in seconds
default: 600
wait_timeout_redirects:
description:
- how long before wait gives up for redirects, in seconds
default: 300
state:
description:
- create or terminate instances
choices: [ absent, present ]
default: 'present'
auto_updates:
description:
- Enable Auto Updates on Windows Machines
version_added: "2.0"
type: bool
default: 'no'
enable_winrm:
description:
- Enable winrm on Windows Machines
version_added: "2.0"
type: bool
default: 'yes'
os_type:
description:
- The type of the os that is gettings provisioned
version_added: "2.0"
default: "linux"
choices: [ "windows", "linux" ]
requirements:
- "python >= 2.6"
- "azure >= 0.7.1"
author: "John Whitbeck (@jwhitbeck)"
'''
EXAMPLES = '''
# Note: None of these examples set subscription_id or management_cert_path
# It is assumed that their matching environment variables are set.
- name: Provision virtual machine example
azure:
name: my-virtual-machine
role_size: Small
image: b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-precise-12_04_3-LTS-amd64-server-20131205-en-us-30GB
location: East US
user: ubuntu
ssh_cert_path: /path/to/azure_x509_cert.pem
storage_account: my-storage-account
wait: True
state: present
delegate_to: localhost
- name: Terminate virtual machine example
azure:
name: my-virtual-machine
state: absent
delegate_to: localhost
- name: Create windows machine
azure:
name: ben-Winows-23
hostname: win123
os_type: windows
enable_winrm: True
subscription_id: '{{ azure_sub_id }}'
management_cert_path: '{{ azure_cert_path }}'
role_size: Small
image: bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-v13.5
location: East Asia
password: xxx
storage_account: benooytes
user: admin
wait: True
state: present
virtual_network_name: '{{ vnet_name }}'
delegate_to: localhost
'''
import base64
import datetime
import os
import signal
import time
from ansible.module_utils.six.moves.urllib.parse import urlparse
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.facts.timeout import TimeoutError
AZURE_LOCATIONS = ['South Central US',
'Central US',
'East US 2',
'East US',
'West US',
'North Central US',
'North Europe',
'West Europe',
'East Asia',
'Southeast Asia',
'Japan West',
'Japan East',
'Brazil South']
AZURE_ROLE_SIZES = ['ExtraSmall',
'Small',
'Medium',
'Large',
'ExtraLarge',
'A5',
'A6',
'A7',
'A8',
'A9',
'Basic_A0',
'Basic_A1',
'Basic_A2',
'Basic_A3',
'Basic_A4',
'Standard_D1',
'Standard_D2',
'Standard_D3',
'Standard_D4',
'Standard_D11',
'Standard_D12',
'Standard_D13',
'Standard_D14',
'Standard_D1_v2',
'Standard_D2_v2',
'Standard_D3_v2',
'Standard_D4_v2',
'Standard_D5_v2',
'Standard_D11_v2',
'Standard_D12_v2',
'Standard_D13_v2',
'Standard_D14_v2',
'Standard_DS1',
'Standard_DS2',
'Standard_DS3',
'Standard_DS4',
'Standard_DS11',
'Standard_DS12',
'Standard_DS13',
'Standard_DS14',
'Standard_G1',
'Standard_G2',
'Standard_G3',
'Standard_G4',
'Standard_G5']
from distutils.version import LooseVersion
try:
import azure as windows_azure
if hasattr(windows_azure, '__version__') and LooseVersion(windows_azure.__version__) <= "0.11.1":
from azure import WindowsAzureError as AzureException
from azure import WindowsAzureMissingResourceError as AzureMissingException
else:
from azure.common import AzureException as AzureException
from azure.common import AzureMissingResourceHttpError as AzureMissingException
from azure.servicemanagement import (ServiceManagementService, OSVirtualHardDisk, SSH, PublicKeys,
PublicKey, LinuxConfigurationSet, ConfigurationSetInputEndpoints,
ConfigurationSetInputEndpoint, Listener, WindowsConfigurationSet)
HAS_AZURE = True
except ImportError:
HAS_AZURE = False
from types import MethodType
import json
def _wait_for_completion(azure, promise, wait_timeout, msg):
if not promise:
return
wait_timeout = time.time() + wait_timeout
while wait_timeout > time.time():
operation_result = azure.get_operation_status(promise.request_id)
time.sleep(5)
if operation_result.status == "Succeeded":
return
raise AzureException('Timed out waiting for async operation ' + msg + ' "' + str(promise.request_id) + '" to complete.')
def _delete_disks_when_detached(azure, wait_timeout, disk_names):
def _handle_timeout(signum, frame):
raise TimeoutError("Timeout reached while waiting for disks to become detached.")
signal.signal(signal.SIGALRM, _handle_timeout)
signal.alarm(wait_timeout)
try:
while len(disk_names) > 0:
for disk_name in disk_names:
disk = azure.get_disk(disk_name)
if disk.attached_to is None:
azure.delete_disk(disk.name, True)
disk_names.remove(disk_name)
except AzureException as e:
raise AzureException("failed to get or delete disk %s, error was: %s" % (disk_name, str(e)))
finally:
signal.alarm(0)
def get_ssh_certificate_tokens(module, ssh_cert_path):
"""
Returns the sha1 fingerprint and a base64-encoded PKCS12 version of the certificate.
"""
# This returns a string such as SHA1 Fingerprint=88:60:0B:13:A9:14:47:DA:4E:19:10:7D:34:92:2B:DF:A1:7D:CA:FF
rc, stdout, stderr = module.run_command(['openssl', 'x509', '-in', ssh_cert_path, '-fingerprint', '-noout'])
if rc != 0:
module.fail_json(msg="failed to generate the key fingerprint, error was: %s" % stderr)
fingerprint = stdout.strip()[17:].replace(':', '')
rc, stdout, stderr = module.run_command(['openssl', 'pkcs12', '-export', '-in', ssh_cert_path, '-nokeys', '-password', 'pass:'])
if rc != 0:
module.fail_json(msg="failed to generate the pkcs12 signature from the certificate, error was: %s" % stderr)
pkcs12_base64 = base64.b64encode(stdout.strip())
return (fingerprint, pkcs12_base64)
def create_virtual_machine(module, azure):
"""
Create new virtual machine
module : AnsibleModule object
azure: authenticated azure ServiceManagementService object
Returns:
True if a new virtual machine and/or cloud service was created, false otherwise
"""
name = module.params.get('name')
os_type = module.params.get('os_type')
hostname = module.params.get('hostname') or name + ".cloudapp.net"
endpoints = module.params.get('endpoints').split(',')
ssh_cert_path = module.params.get('ssh_cert_path')
user = module.params.get('user')
password = module.params.get('password')
location = module.params.get('location')
role_size = module.params.get('role_size')
storage_account = module.params.get('storage_account')
image = module.params.get('image')
virtual_network_name = module.params.get('virtual_network_name')
wait = module.params.get('wait')
wait_timeout = int(module.params.get('wait_timeout'))
changed = False
# Check if a deployment with the same name already exists
cloud_service_name_available = azure.check_hosted_service_name_availability(name)
if cloud_service_name_available.result:
# cloud service does not exist; create it
try:
result = azure.create_hosted_service(service_name=name, label=name, location=location)
_wait_for_completion(azure, result, wait_timeout, "create_hosted_service")
changed = True
except AzureException as e:
module.fail_json(msg="failed to create the new service, error was: %s" % str(e))
try:
# check to see if a vm with this name exists; if so, do nothing
azure.get_role(name, name, name)
except AzureMissingException:
# vm does not exist; create it
if os_type == 'linux':
# Create linux configuration
disable_ssh_password_authentication = not password
vm_config = LinuxConfigurationSet(hostname, user, password, disable_ssh_password_authentication)
else:
# Create Windows Config
vm_config = WindowsConfigurationSet(hostname, password, None, module.params.get('auto_updates'), None, user)
vm_config.domain_join = None
if module.params.get('enable_winrm'):
listener = Listener('Http')
vm_config.win_rm.listeners.listeners.append(listener)
else:
vm_config.win_rm = None
# Add ssh certificates if specified
if ssh_cert_path:
fingerprint, pkcs12_base64 = get_ssh_certificate_tokens(module, ssh_cert_path)
# Add certificate to cloud service
result = azure.add_service_certificate(name, pkcs12_base64, 'pfx', '')
_wait_for_completion(azure, result, wait_timeout, "add_service_certificate")
# Create ssh config
ssh_config = SSH()
ssh_config.public_keys = PublicKeys()
authorized_keys_path = u'/home/%s/.ssh/authorized_keys' % user
ssh_config.public_keys.public_keys.append(PublicKey(path=authorized_keys_path, fingerprint=fingerprint))
# Append ssh config to linux machine config
vm_config.ssh = ssh_config
# Create network configuration
network_config = ConfigurationSetInputEndpoints()
network_config.configuration_set_type = 'NetworkConfiguration'
network_config.subnet_names = []
network_config.public_ips = None
for port in endpoints:
network_config.input_endpoints.append(ConfigurationSetInputEndpoint(name='TCP-%s' % port,
protocol='TCP',
port=port,
local_port=port))
# First determine where to store disk
today = datetime.date.today().strftime('%Y-%m-%d')
disk_prefix = u'%s-%s' % (name, name)
media_link = u'http://%s.blob.core.windows.net/vhds/%s-%s.vhd' % (storage_account, disk_prefix, today)
# Create system hard disk
os_hd = OSVirtualHardDisk(image, media_link)
# Spin up virtual machine
try:
result = azure.create_virtual_machine_deployment(service_name=name,
deployment_name=name,
deployment_slot='production',
label=name,
role_name=name,
system_config=vm_config,
network_config=network_config,
os_virtual_hard_disk=os_hd,
role_size=role_size,
role_type='PersistentVMRole',
virtual_network_name=virtual_network_name)
_wait_for_completion(azure, result, wait_timeout, "create_virtual_machine_deployment")
changed = True
except AzureException as e:
module.fail_json(msg="failed to create the new virtual machine, error was: %s" % str(e))
try:
deployment = azure.get_deployment_by_name(service_name=name, deployment_name=name)
return (changed, urlparse(deployment.url).hostname, deployment)
except AzureException as e:
module.fail_json(msg="failed to lookup the deployment information for %s, error was: %s" % (name, str(e)))
def terminate_virtual_machine(module, azure):
"""
Terminates a virtual machine
module : AnsibleModule object
azure: authenticated azure ServiceManagementService object
Returns:
True if a new virtual machine was deleted, false otherwise
"""
# Whether to wait for termination to complete before returning
wait = module.params.get('wait')
wait_timeout = int(module.params.get('wait_timeout'))
name = module.params.get('name')
delete_empty_services = module.params.get('delete_empty_services')
changed = False
deployment = None
public_dns_name = None
disk_names = []
try:
deployment = azure.get_deployment_by_name(service_name=name, deployment_name=name)
except AzureMissingException as e:
pass # no such deployment or service
except AzureException as e:
module.fail_json(msg="failed to find the deployment, error was: %s" % str(e))
# Delete deployment
if deployment:
changed = True
try:
# gather disk info
results = []
for role in deployment.role_list:
role_props = azure.get_role(name, deployment.name, role.role_name)
if role_props.os_virtual_hard_disk.disk_name not in disk_names:
disk_names.append(role_props.os_virtual_hard_disk.disk_name)
except AzureException as e:
module.fail_json(msg="failed to get the role %s, error was: %s" % (role.role_name, str(e)))
try:
result = azure.delete_deployment(name, deployment.name)
_wait_for_completion(azure, result, wait_timeout, "delete_deployment")
except AzureException as e:
module.fail_json(msg="failed to delete the deployment %s, error was: %s" % (deployment.name, str(e)))
# It's unclear when disks associated with terminated deployment get detached.
# Thus, until the wait_timeout is reached, we continue to delete disks as they
# become detached by polling the list of remaining disks and examining the state.
try:
_delete_disks_when_detached(azure, wait_timeout, disk_names)
except (AzureException, TimeoutError) as e:
module.fail_json(msg=str(e))
try:
# Now that the vm is deleted, remove the cloud service
result = azure.delete_hosted_service(service_name=name)
_wait_for_completion(azure, result, wait_timeout, "delete_hosted_service")
except AzureException as e:
module.fail_json(msg="failed to delete the service %s, error was: %s" % (name, str(e)))
public_dns_name = urlparse(deployment.url).hostname
return changed, public_dns_name, deployment
def get_azure_creds(module):
# Check module args for credentials, then check environment vars
subscription_id = module.params.get('subscription_id')
if not subscription_id:
subscription_id = os.environ.get('AZURE_SUBSCRIPTION_ID', None)
if not subscription_id:
module.fail_json(msg="No subscription_id provided. Please set 'AZURE_SUBSCRIPTION_ID' or use the 'subscription_id' parameter")
management_cert_path = module.params.get('management_cert_path')
if not management_cert_path:
management_cert_path = os.environ.get('AZURE_CERT_PATH', None)
if not management_cert_path:
module.fail_json(msg="No management_cert_path provided. Please set 'AZURE_CERT_PATH' or use the 'management_cert_path' parameter")
return subscription_id, management_cert_path
def main():
module = AnsibleModule(
argument_spec=dict(
ssh_cert_path=dict(),
name=dict(),
hostname=dict(),
os_type=dict(default='linux', choices=['linux', 'windows']),
location=dict(choices=AZURE_LOCATIONS),
role_size=dict(choices=AZURE_ROLE_SIZES),
subscription_id=dict(no_log=True),
storage_account=dict(),
management_cert_path=dict(),
endpoints=dict(default='22'),
user=dict(),
password=dict(no_log=True),
image=dict(),
virtual_network_name=dict(default=None),
state=dict(default='present'),
wait=dict(type='bool', default=False),
wait_timeout=dict(default=600),
wait_timeout_redirects=dict(default=300),
auto_updates=dict(type='bool', default=False),
enable_winrm=dict(type='bool', default=True),
)
)
if not HAS_AZURE:
module.fail_json(msg='azure python module required for this module')
# create azure ServiceManagementService object
subscription_id, management_cert_path = get_azure_creds(module)
wait_timeout_redirects = int(module.params.get('wait_timeout_redirects'))
if hasattr(windows_azure, '__version__') and LooseVersion(windows_azure.__version__) <= "0.8.0":
# wrapper for handling redirects which the sdk <= 0.8.0 is not following
azure = Wrapper(ServiceManagementService(subscription_id, management_cert_path), wait_timeout_redirects)
else:
azure = ServiceManagementService(subscription_id, management_cert_path)
cloud_service_raw = None
if module.params.get('state') == 'absent':
(changed, public_dns_name, deployment) = terminate_virtual_machine(module, azure)
elif module.params.get('state') == 'present':
# Changed is always set to true when provisioning new instances
if not module.params.get('name'):
module.fail_json(msg='name parameter is required for new instance')
if not module.params.get('image'):
module.fail_json(msg='image parameter is required for new instance')
if not module.params.get('user'):
module.fail_json(msg='user parameter is required for new instance')
if not module.params.get('location'):
module.fail_json(msg='location parameter is required for new instance')
if not module.params.get('storage_account'):
module.fail_json(msg='storage_account parameter is required for new instance')
if not (module.params.get('password') or module.params.get('ssh_cert_path')):
module.fail_json(msg='password or ssh_cert_path parameter is required for new instance')
(changed, public_dns_name, deployment) = create_virtual_machine(module, azure)
module.exit_json(changed=changed, public_dns_name=public_dns_name, deployment=json.loads(json.dumps(deployment, default=lambda o: o.__dict__)))
class Wrapper(object):
def __init__(self, obj, wait_timeout):
self.other = obj
self.wait_timeout = wait_timeout
def __getattr__(self, name):
if hasattr(self.other, name):
func = getattr(self.other, name)
return lambda *args, **kwargs: self._wrap(func, args, kwargs)
raise AttributeError(name)
def _wrap(self, func, args, kwargs):
if isinstance(func, MethodType):
result = self._handle_temporary_redirects(lambda: func(*args, **kwargs))
else:
result = self._handle_temporary_redirects(lambda: func(self.other, *args, **kwargs))
return result
def _handle_temporary_redirects(self, f):
wait_timeout = time.time() + self.wait_timeout
while wait_timeout > time.time():
try:
return f()
except AzureException as e:
if not str(e).lower().find("temporary redirect") == -1:
time.sleep(5)
else:
raise e
if __name__ == '__main__': if __name__ == '__main__':
main() removed_module(removed_in='2.8')

View file

@ -8,274 +8,12 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['deprecated'], 'status': ['removed'],
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = '''
---
module: cs_nic
short_description: Manages NICs and secondary IPs of an instance on Apache CloudStack based clouds
description:
- Add and remove secondary IPs to and from a NIC.
version_added: "2.3"
author:
- René Moser (@resmo)
deprecated:
removed_in: "2.8"
why: New module created.
alternative: Use M(cs_instance_nic_secondaryip) instead.
options:
vm:
description:
- Name of instance.
required: true
aliases: [ name ]
network:
description:
- Name of the network.
- Required to find the NIC if instance has multiple networks assigned.
vm_guest_ip:
description:
- Secondary IP address to be added to the instance nic.
- If not set, the API always returns a new IP address and idempotency is not given.
aliases: [ secondary_ip ]
vpc:
description:
- Name of the VPC the C(vm) is related to.
domain:
description:
- Domain the instance is related to.
account:
description:
- Account the instance is related to.
project:
description:
- Name of the project the instance is deployed in.
zone:
description:
- Name of the zone in which the instance is deployed in.
- If not set, default zone is used.
state:
description:
- State of the ipaddress.
choices: [ absent, present ]
default: present
poll_async:
description:
- Poll async jobs until job has finished.
type: bool
default: 'yes'
extends_documentation_fragment: cloudstack
'''
EXAMPLES = ''' from ansible.module_utils.common.removed import removed_module
- name: Assign a specific IP to the default NIC of the VM
local_action:
module: cs_nic
vm: customer_xy
vm_guest_ip: 10.10.10.10
# Note: If vm_guest_ip is not set, you will get a new IP address on every run.
- name: Assign an IP to the default NIC of the VM
local_action:
module: cs_nic
vm: customer_xy
- name: Remove a specific IP from the default NIC
local_action:
module: cs_nic
vm: customer_xy
vm_guest_ip: 10.10.10.10
state: absent
'''
RETURN = '''
---
id:
description: UUID of the nic.
returned: success
type: string
sample: 87b1e0ce-4e01-11e4-bb66-0050569e64b8
vm:
description: Name of the VM.
returned: success
type: string
sample: web-01
ip_address:
description: Primary IP of the NIC.
returned: success
type: string
sample: 10.10.10.10
netmask:
description: Netmask of the NIC.
returned: success
type: string
sample: 255.255.255.0
mac_address:
description: MAC address of the NIC.
returned: success
type: string
sample: 02:00:33:31:00:e4
vm_guest_ip:
description: Secondary IP of the NIC.
returned: success
type: string
sample: 10.10.10.10
network:
description: Name of the network if not default.
returned: success
type: string
sample: sync network
domain:
description: Domain the VM is related to.
returned: success
type: string
sample: example domain
account:
description: Account the VM is related to.
returned: success
type: string
sample: example account
project:
description: Name of project the VM is related to.
returned: success
type: string
sample: Production
'''
try:
from cs import CloudStackException
except ImportError:
pass # Handled in AnsibleCloudStack.__init__
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.cloudstack import AnsibleCloudStack, cs_argument_spec, cs_required_together
class AnsibleCloudStackNic(AnsibleCloudStack):
def __init__(self, module):
super(AnsibleCloudStackNic, self).__init__(module)
self.vm_guest_ip = self.module.params.get('vm_guest_ip')
self.nic = None
self.returns = {
'ipaddress': 'ip_address',
'macaddress': 'mac_address',
'netmask': 'netmask',
}
def get_nic(self):
if self.nic:
return self.nic
args = {
'virtualmachineid': self.get_vm(key='id'),
'networkid': self.get_network(key='id'),
}
nics = self.cs.listNics(**args)
if nics:
self.nic = nics['nic'][0]
return self.nic
self.module.fail_json(msg="NIC for VM %s in network %s not found" % (self.get_vm(key='name'), self.get_network(key='name')))
def get_secondary_ip(self):
nic = self.get_nic()
if self.vm_guest_ip:
secondary_ips = nic.get('secondaryip') or []
for secondary_ip in secondary_ips:
if secondary_ip['ipaddress'] == self.vm_guest_ip:
return secondary_ip
return None
def present_nic(self):
nic = self.get_nic()
if not self.get_secondary_ip():
self.result['changed'] = True
args = {
'nicid': nic['id'],
'ipaddress': self.vm_guest_ip,
}
if not self.module.check_mode:
res = self.cs.addIpToNic(**args)
if 'errortext' in res:
self.module.fail_json(msg="Failed: '%s'" % res['errortext'])
poll_async = self.module.params.get('poll_async')
if poll_async:
nic = self.poll_job(res, 'nicsecondaryip')
# Save result for RETURNS
self.vm_guest_ip = nic['ipaddress']
return nic
def absent_nic(self):
nic = self.get_nic()
secondary_ip = self.get_secondary_ip()
if secondary_ip:
self.result['changed'] = True
if not self.module.check_mode:
res = self.cs.removeIpFromNic(id=secondary_ip['id'])
if 'errortext' in res:
self.module.fail_json(msg="Failed: '%s'" % nic['errortext'])
poll_async = self.module.params.get('poll_async')
if poll_async:
self.poll_job(res, 'nicsecondaryip')
return nic
def get_result(self, nic):
super(AnsibleCloudStackNic, self).get_result(nic)
if nic and not self.module.params.get('network'):
self.module.params['network'] = nic.get('networkid')
self.result['network'] = self.get_network(key='name')
self.result['vm'] = self.get_vm(key='name')
self.result['vm_guest_ip'] = self.vm_guest_ip
self.result['domain'] = self.get_domain(key='path')
self.result['account'] = self.get_account(key='name')
self.result['project'] = self.get_project(key='name')
return self.result
def main():
argument_spec = cs_argument_spec()
argument_spec.update(dict(
vm=dict(type='str', required=True, aliases=['name']),
vm_guest_ip=dict(type='str', aliases=['secondary_ip']),
network=dict(type='str',),
vpc=dict(type='str'),
state=dict(type='str', default='present', choices=['absent', 'present']),
domain=dict(type='str'),
account=dict(type='str'),
project=dict(type='str'),
zone=dict(type='str'),
poll_async=dict(type='bool', default=True),
))
module = AnsibleModule(
argument_spec=argument_spec,
required_together=cs_required_together(),
supports_check_mode=True,
required_if=([
('state', 'absent', ['vm_guest_ip'])
])
)
try:
acs_nic = AnsibleCloudStackNic(module)
state = module.params.get('state')
if state == 'absent':
nic = acs_nic.absent_nic()
else:
nic = acs_nic.present_nic()
result = acs_nic.get_result(nic)
except CloudStackException as e:
module.fail_json(msg='CloudStackException: %s' % str(e))
module.exit_json(**result)
if __name__ == '__main__': if __name__ == '__main__':
main() removed_module(removed_in='2.8')

View file

@ -8,180 +8,12 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['deprecated'], 'status': ['removed'],
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = '''
---
module: netscaler
version_added: "1.1"
short_description: Manages Citrix NetScaler entities
description:
- Manages Citrix NetScaler server and service entities.
deprecated:
removed_in: "2.8"
why: Replaced with Citrix maintained version.
alternative: Use M(netscaler_service) and M(netscaler_server) instead.
options:
nsc_host:
description:
- Hostname or ip of your netscaler.
required: true
nsc_protocol:
description:
- Protocol used to access netscaler.
default: https
user:
description:
- Username.
required: true
password:
description:
- Password.
required: true
action:
description:
- The action you want to perform on the entity.
choices: [ disable, enable ]
default: disable
name:
description:
- Name of the entity.
required: true
default: hostname
type:
description:
- Type of the entity.
choices: [ server, service ]
default: server
validate_certs:
description:
- If C(no), SSL certificates for the target url will not be validated.
- This should only be used on personally controlled sites using self-signed certificates.
type: bool
default: 'yes'
author:
- Nandor Sivok (@dominis)
'''
EXAMPLES = ''' from ansible.module_utils.common.removed import removed_module
- name: Disable the server
netscaler:
nsc_host: nsc.example.com
user: apiuser
password: apipass
- name: Enable the server
netscaler:
nsc_host: nsc.example.com
user: apiuser
password: apipass
action: enable
- name: Disable the service local:8080
netscaler:
nsc_host: nsc.example.com
user: apiuser
password: apipass
name: local:8080
type: service
action: disable
'''
import json
import socket
import traceback
import base64
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils._text import to_native, to_bytes
from ansible.module_utils.urls import fetch_url
class netscaler(object):
_nitro_base_url = '/nitro/v1/'
def __init__(self, module):
self.module = module
def http_request(self, api_endpoint, data_json=None):
data_josn = {} if data_json is None else data_json
request_url = self._nsc_protocol + '://' + self._nsc_host + self._nitro_base_url + api_endpoint
data_json = urlencode(data_json)
if not len(data_json):
data_json = None
auth = base64.b64encode(to_bytes('%s:%s' % (self._nsc_user, self._nsc_pass)).replace('\n', '').strip())
headers = {
'Authorization': 'Basic %s' % auth,
'Content-Type': 'application/x-www-form-urlencoded',
}
response, info = fetch_url(self.module, request_url, data=data_json, headers=headers)
return json.load(response)
def prepare_request(self, action):
resp = self.http_request(
'config',
{
"object":
{
"params": {"action": action},
self._type: {"name": self._name}
}
}
)
return resp
def core(module):
n = netscaler(module)
n._nsc_host = module.params.get('nsc_host')
n._nsc_user = module.params.get('user')
n._nsc_pass = module.params.get('password')
n._nsc_protocol = module.params.get('nsc_protocol')
n._name = module.params.get('name')
n._type = module.params.get('type')
action = module.params.get('action')
r = n.prepare_request(action)
return r['errorcode'], r
def main():
module = AnsibleModule(
argument_spec=dict(
nsc_host=dict(type='str', required=True),
nsc_protocol=dict(type='str', default='https'),
user=dict(type='str', required=True),
password=dict(type='str', required=True, no_log=True),
action=dict(type='str', default='enable', choices=['disable', 'enable']),
name=dict(type='str', default=socket.gethostname()),
type=dict(type='str', default='server', choices=['server', 'service']),
validate_certs=dict(type='bool', default=True),
),
)
rc = 0
try:
rc, result = core(module)
except Exception as e:
module.fail_json(msg=to_native(e), exception=traceback.format_exc())
if rc != 0:
module.fail_json(rc=rc, msg=result)
else:
result['changed'] = True
module.exit_json(**result)
if __name__ == '__main__': if __name__ == '__main__':
main() removed_module(removed_in='2.8')

View file

@ -8,80 +8,12 @@
# file of the same name # file of the same name
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['deprecated'], 'status': ['removed'],
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = r'''
---
module: win_msi
version_added: '1.7'
deprecated:
removed_in: "2.8"
why: The win_msi module has a number of issues, the M(win_package) module is easier to maintain and use.
alternative: Use M(win_package) instead.
short_description: Installs and uninstalls Windows MSI files
description:
- Installs or uninstalls a Windows MSI file that is already located on the
target server.
options:
path:
description:
- File system path to the MSI file to install.
required: yes
type: path
extra_args:
description:
- Additional arguments to pass to the msiexec.exe command.
state:
description:
- Whether the MSI file should be installed or uninstalled.
choices: [ absent, present ]
default: present
creates:
description:
- Path to a file created by installing the MSI to prevent from
attempting to reinstall the package on every run.
type: path
removes:
description:
- Path to a file removed by uninstalling the MSI to prevent from
attempting to re-uninstall the package on every run.
type: path
version_added: '2.4'
wait:
description:
- Specify whether to wait for install or uninstall to complete before continuing.
type: bool
default: 'no'
version_added: '2.1'
notes:
- This module is not idempotent and will report a change every time.
Use the C(creates) and C(removes) options to your advantage.
- Please look into M(win_package) instead, this package will be deprecated in the future.
author:
- Matt Martz (@sivel)
'''
EXAMPLES = r''' from ansible.module_utils.common.removed import removed_module
- name: Install an MSI file
win_msi:
path: C:\7z920-x64.msi
- name: Install an MSI, and wait for it to complete before continuing
win_msi:
path: C:\7z920-x64.msi
wait: yes
- name: Uninstall an MSI file if __name__ == '__main__':
win_msi: removed_module(removed_in='2.8')
path: C:\7z920-x64.msi
state: absent
'''
RETURN = r'''
log:
description: The logged output from the installer
returned: always
type: string
sample: N/A
'''

View file

@ -13,3 +13,8 @@ ec2_facts
ec2_vpc ec2_vpc
nxos_mtu nxos_mtu
s3 s3
azure
cs_nic
ec2_remote_facts
netscaler
win_msi

View file

@ -139,8 +139,6 @@ lib/ansible/modules/cloud/amazon/s3_website.py E324
lib/ansible/modules/cloud/amazon/sns_topic.py E325 lib/ansible/modules/cloud/amazon/sns_topic.py E325
lib/ansible/modules/cloud/amazon/sts_assume_role.py E317 lib/ansible/modules/cloud/amazon/sts_assume_role.py E317
lib/ansible/modules/cloud/atomic/atomic_container.py E317 lib/ansible/modules/cloud/atomic/atomic_container.py E317
lib/ansible/modules/cloud/azure/_azure.py E324
lib/ansible/modules/cloud/azure/_azure.py E326
lib/ansible/modules/cloud/centurylink/clc_alert_policy.py E317 lib/ansible/modules/cloud/centurylink/clc_alert_policy.py E317
lib/ansible/modules/cloud/centurylink/clc_firewall_policy.py E317 lib/ansible/modules/cloud/centurylink/clc_firewall_policy.py E317
lib/ansible/modules/cloud/centurylink/clc_firewall_policy.py E324 lib/ansible/modules/cloud/centurylink/clc_firewall_policy.py E324
@ -647,7 +645,6 @@ lib/ansible/modules/network/aos/_aos_blueprint_param.py E325
lib/ansible/modules/network/asa/asa_config.py E324 lib/ansible/modules/network/asa/asa_config.py E324
lib/ansible/modules/network/bigswitch/bigmon_policy.py E324 lib/ansible/modules/network/bigswitch/bigmon_policy.py E324
lib/ansible/modules/network/bigswitch/bigmon_policy.py E326 lib/ansible/modules/network/bigswitch/bigmon_policy.py E326
lib/ansible/modules/network/citrix/_netscaler.py E324
lib/ansible/modules/network/cloudengine/ce_aaa_server.py E322 lib/ansible/modules/network/cloudengine/ce_aaa_server.py E322
lib/ansible/modules/network/cloudengine/ce_aaa_server_host.py E322 lib/ansible/modules/network/cloudengine/ce_aaa_server_host.py E322
lib/ansible/modules/network/cloudengine/ce_acl.py E322 lib/ansible/modules/network/cloudengine/ce_acl.py E322