Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
ansible
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
ansible
Commits
234a7867
Commit
234a7867
authored
Nov 15, 2013
by
Matt Martz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor rax module
parent
af0cdd46
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
500 additions
and
178 deletions
+500
-178
library/cloud/rax
+500
-178
No files found.
library/cloud/rax
View file @
234a7867
...
@@ -19,82 +19,111 @@ DOCUMENTATION = '''
...
@@ -19,82 +19,111 @@ DOCUMENTATION = '''
module: rax
module: rax
short_description: create / delete an instance in Rackspace Public Cloud
short_description: create / delete an instance in Rackspace Public Cloud
description:
description:
- creates / deletes a Rackspace Public Cloud instance and optionally waits for it to be 'running'.
- creates / deletes a Rackspace Public Cloud instance and optionally
waits for it to be 'running'.
version_added: "1.2"
version_added: "1.2"
options:
options:
service
:
api_key
:
description:
description:
- Cloud service to interact with
- Rackspace API key (overrides I(credentials))
choices: ['cloudservers']
count:
default: cloudservers
state:
description:
description:
- Indicate desired state of the resource
- number of instances to launch
choices: ['present', 'active', 'absent', 'deleted']
default: 1
default: present
version_added: 1.4
count_offset:
description:
- number count to start at
default: 1
version_added: 1.4
credentials:
credentials:
description:
description:
- File to find the Rackspace credentials in (ignored if C
(api_key) and
- File to find the Rackspace credentials in (ignored if I
(api_key) and
C
(username) are provided)
I
(username) are provided)
default: null
default: null
aliases: ['creds_file']
aliases: ['creds_file']
api_key
:
disk_config
:
description:
description:
- Rackspace API key (overrides C(credentials))
- Disk partitioning strategy
username:
choices: ['auto', 'manual']
version_added: '1.4'
default: auto
exact_count:
description:
description:
- Rackspace username (overrides C(credentials))
- Explicitly ensure an exact count of instances, used with
name:
state=active/present
default: no
version_added: 1.4
files:
description:
description:
- Name to give the instance
- Files to insert into the instance. remotefilename:localcontent
default: null
default: null
flavor:
flavor:
description:
description:
- flavor to use for the instance
- flavor to use for the instance
default: null
default: null
group:
description:
- host group to assign to server, is also used for idempotent operations
to ensure a specific number of instances
version_added: 1.4
image:
image:
description:
description:
- image to use for the instance
- image to use for the instance. Can be an C(id), C(human_id) or C(name)
default: null
default: null
meta
:
instance_ids
:
description:
description:
- A hash of metadata to associate with the instance
- list of instance ids, currently only used when state='absent' to
default: null
remove instances
version_added: 1.4
key_name:
key_name:
description:
description:
- key pair to use on the instance
- key pair to use on the instance
default: null
default: null
aliases: ['keypair']
aliases: ['keypair']
files
:
meta
:
description:
description:
- Files to insert into the instance. remotefilename:localcontent
- A hash of metadata to associate with the instance
default: null
default: null
name:
description:
- Name to give the instance
default: null
networks:
description:
- The network to attach to the instances. If specified, you must include
ALL networks including the public and private interfaces. Can be C(id)
or C(label).
default: ['public', 'private']
version_added: 1.4
region:
region:
description:
description:
- Region to create an instance in
- Region to create an instance in
default: DFW
default: DFW
disk_config
:
state
:
description:
description:
- Disk partitioning strategy
- Indicate desired state of the resource
choices: ['auto', 'manual']
choices: ['present', 'absent']
version_added: '1.4'
default: present
default: auto
username:
description:
- Rackspace username (overrides I(credentials))
wait:
wait:
description:
description:
- wait for the instance to be in state 'running' before returning
- wait for the instance to be in state 'running' before returning
default: "no"
default: "no"
choices: [ "yes", "no" ]
choices: [ "yes", "no" ]
wait_timeout:
wait_timeout:
description:
description:
- how long before wait gives up, in seconds
- how long before wait gives up, in seconds
default: 300
default: 300
requirements: [ "pyrax" ]
requirements: [ "pyrax" ]
author: Jesse Keating
author: Jesse Keating
, Matt Martz
notes:
notes:
- The following environment variables can be used, C(RAX_USERNAME),
- The following environment variables can be used, C(RAX_USERNAME),
C(RAX_API_KEY), C(RAX_CREDS), C(RAX_CREDENTIALS), C(RAX_REGION).
C(RAX_API_KEY), C(RAX_CREDS
_FILE
), C(RAX_CREDENTIALS), C(RAX_REGION).
- C(RAX_CREDENTIALS) and C(RAX_CREDS) points to a credentials file
- C(RAX_CREDENTIALS) and C(RAX_CREDS
_FILE
) points to a credentials file
appropriate for pyrax
appropriate for pyrax
. See U(https://github.com/rackspace/pyrax/blob/master/docs/getting_started.md#authenticating)
- C(RAX_USERNAME) and C(RAX_API_KEY) obviate the use of a credentials file
- C(RAX_USERNAME) and C(RAX_API_KEY) obviate the use of a credentials file
- C(RAX_REGION) defines a Rackspace Public Cloud region (DFW, ORD, LON, ...)
- C(RAX_REGION) defines a Rackspace Public Cloud region (DFW, ORD, LON, ...)
'''
'''
...
@@ -102,13 +131,11 @@ notes:
...
@@ -102,13 +131,11 @@ notes:
EXAMPLES
=
'''
EXAMPLES
=
'''
- name: Build a Cloud Server
- name: Build a Cloud Server
gather_facts: False
gather_facts: False
tasks:
tasks:
- name: Server build request
- name: Server build request
local_action:
local_action:
module: rax
module: rax
credentials: ~/.raxpub
credentials: ~/.raxpub
service: cloudservers
name: rax-test1
name: rax-test1
flavor: 5
flavor: 5
image: b11d9567-e412-4255-96b9-bd63ab23bcfe
image: b11d9567-e412-4255-96b9-bd63ab23bcfe
...
@@ -117,179 +144,479 @@ EXAMPLES = '''
...
@@ -117,179 +144,479 @@ EXAMPLES = '''
/root/test.txt: /home/localuser/test.txt
/root/test.txt: /home/localuser/test.txt
wait: yes
wait: yes
state: present
state: present
networks:
- private
- public
'''
'''
import
sys
import
sys
import
time
import
time
import
os
import
os
import
re
from
uuid
import
UUID
from
types
import
NoneType
try
:
try
:
import
pyrax
import
pyrax
import
pyrax.utils
except
ImportError
:
except
ImportError
:
print
(
"failed=True msg='pyrax required for this module'"
)
print
(
"failed=True msg='pyrax
is
required for this module'"
)
sys
.
exit
(
1
)
sys
.
exit
(
1
)
# These are possible services, but only cloudservers is supported at this time
ACTIVE_STATUSES
=
(
'ACTIVE'
,
'BUILD'
,
'HARD_REBOOT'
,
'MIGRATING'
,
'PASSWORD'
,
#SUPPORTEDSERVICES = ['cloudservers', 'cloudfiles', 'cloud_blockstorage',
'REBOOT'
,
'REBUILD'
,
'RESCUE'
,
'RESIZE'
,
'REVERT_RESIZE'
)
# 'cloud_databases', 'cloud_loadbalancers']
FINAL_STATUSES
=
(
'ACTIVE'
,
'ERROR'
)
SUPPORTEDSERVICES
=
[
'cloudservers'
]
NON_CALLABLES
=
(
basestring
,
bool
,
dict
,
int
,
list
,
NoneType
)
PUBLIC_NET_ID
=
"00000000-0000-0000-0000-000000000000"
SERVICE_NET_ID
=
"11111111-1111-1111-1111-111111111111"
def
cloudservers
(
module
,
state
,
name
,
flavor
,
image
,
meta
,
key_name
,
files
,
wait
,
wait_timeout
,
disk_config
):
# Check our args (this could be done better)
for
arg
in
(
state
,
name
,
flavor
,
image
):
if
not
arg
:
module
.
fail_json
(
msg
=
'
%
s is required for cloudservers'
%
arg
)
instances
=
[]
def
rax_slugify
(
value
):
return
'rax_
%
s'
%
(
re
.
sub
(
'[^
\
w-]'
,
'_'
,
value
)
.
lower
()
.
lstrip
(
'_'
))
def
pyrax_object_to_dict
(
obj
):
instance
=
{}
for
key
in
dir
(
obj
):
value
=
getattr
(
obj
,
key
)
if
(
isinstance
(
value
,
NON_CALLABLES
)
and
not
key
.
startswith
(
'_'
)):
key
=
rax_slugify
(
key
)
instance
[
key
]
=
value
for
attr
in
[
'id'
,
'accessIPv4'
,
'name'
,
'status'
]:
instance
[
attr
]
=
instance
.
get
(
rax_slugify
(
attr
))
return
instance
def
create
(
module
,
names
,
flavor
,
image
,
meta
,
key_name
,
files
,
wait
,
wait_timeout
,
disk_config
,
group
,
nics
):
cs
=
pyrax
.
cloudservers
changed
=
False
# Handle the file contents
for
rpath
in
files
.
keys
():
lpath
=
os
.
path
.
expanduser
(
files
[
rpath
])
try
:
fileobj
=
open
(
lpath
,
'r'
)
files
[
rpath
]
=
fileobj
except
Exception
,
e
:
module
.
fail_json
(
msg
=
'Failed to load
%
s'
%
lpath
)
try
:
servers
=
[]
for
name
in
names
:
servers
.
append
(
cs
.
servers
.
create
(
name
=
name
,
image
=
image
,
flavor
=
flavor
,
meta
=
meta
,
key_name
=
key_name
,
files
=
files
,
nics
=
nics
,
disk_config
=
disk_config
))
except
Exception
,
e
:
module
.
fail_json
(
msg
=
'
%
s'
%
e
.
message
)
else
:
changed
=
True
if
wait
:
end_time
=
time
.
time
()
+
wait_timeout
infinite
=
wait_timeout
==
0
while
infinite
or
time
.
time
()
<
end_time
:
for
server
in
servers
:
try
:
server
.
get
()
except
:
server
.
status
==
'ERROR'
if
not
filter
(
lambda
s
:
s
.
status
not
in
FINAL_STATUSES
,
servers
):
break
time
.
sleep
(
5
)
success
=
[]
error
=
[]
timeout
=
[]
for
server
in
servers
:
try
:
server
.
get
()
except
:
server
.
status
==
'ERROR'
instance
=
pyrax_object_to_dict
(
server
)
if
server
.
status
==
'ACTIVE'
or
not
wait
:
success
.
append
(
instance
)
elif
server
.
status
==
'ERROR'
:
error
.
append
(
instance
)
elif
wait
:
timeout
.
append
(
instance
)
results
=
{
'changed'
:
changed
,
'action'
:
'create'
,
'instances'
:
success
+
error
+
timeout
,
'success'
:
success
,
'error'
:
error
,
'timeout'
:
timeout
,
'instance_ids'
:
{
'instances'
:
[
i
[
'id'
]
for
i
in
success
+
error
+
timeout
],
'success'
:
[
i
[
'id'
]
for
i
in
success
],
'error'
:
[
i
[
'id'
]
for
i
in
error
],
'timeout'
:
[
i
[
'id'
]
for
i
in
timeout
]
}
}
if
timeout
:
results
[
'msg'
]
=
'Timeout waiting for all servers to build'
elif
error
:
results
[
'msg'
]
=
'Failed to build all servers'
if
'msg'
in
results
:
module
.
fail_json
(
**
results
)
else
:
module
.
exit_json
(
**
results
)
def
delete
(
module
,
instance_ids
,
wait
,
wait_timeout
):
cs
=
pyrax
.
cloudservers
changed
=
False
changed
=
False
instances
=
{}
servers
=
[]
servers
=
[]
# See if we can find servers that match our options
for
server
in
pyrax
.
cloudservers
.
list
():
if
name
!=
server
.
name
:
continue
if
int
(
flavor
)
!=
int
(
server
.
flavor
[
'id'
]):
continue
if
image
!=
server
.
image
[
'id'
]:
continue
if
meta
!=
server
.
metadata
:
continue
# Nothing else ruled us not a match, so consider it a winner
servers
.
append
(
server
)
# act on the state
for
instance_id
in
instance_ids
:
if
state
in
(
'active'
,
'present'
):
servers
.
append
(
cs
.
servers
.
get
(
instance_id
))
if
not
servers
:
# Handle the file contents
for
server
in
servers
:
for
rpath
in
files
.
keys
():
try
:
lpath
=
os
.
path
.
expanduser
(
files
[
rpath
])
server
.
delete
()
except
Exception
,
e
:
module
.
fail_json
(
msg
=
e
.
message
)
else
:
changed
=
True
instance
=
pyrax_object_to_dict
(
server
)
instances
[
instance
[
'id'
]]
=
instance
# If requested, wait for server deletion
if
wait
:
end_time
=
time
.
time
()
+
wait_timeout
infinite
=
wait_timeout
==
0
while
infinite
or
time
.
time
()
<
end_time
:
for
server
in
servers
:
instance_id
=
server
.
id
try
:
try
:
fileobj
=
open
(
lpath
,
'r'
)
server
.
get
()
files
[
rpath
]
=
fileobj
except
:
except
Exception
,
e
:
instances
[
instance_id
][
'status'
]
=
'DELETED'
module
.
fail_json
(
msg
=
'Failed to load
%
s'
%
lpath
)
if
not
filter
(
lambda
s
:
s
[
'status'
]
not
in
(
''
,
'DELETED'
,
'ERROR'
),
instances
.
values
()):
break
time
.
sleep
(
5
)
timeout
=
filter
(
lambda
s
:
s
[
'status'
]
not
in
(
''
,
'DELETED'
,
'ERROR'
),
instances
.
values
())
error
=
filter
(
lambda
s
:
s
[
'status'
]
in
(
'ERROR'
),
instances
.
values
())
success
=
filter
(
lambda
s
:
s
[
'status'
]
in
(
''
,
'DELETED'
),
instances
.
values
())
results
=
{
'changed'
:
changed
,
'action'
:
'delete'
,
'instances'
:
success
+
error
+
timeout
,
'success'
:
success
,
'error'
:
error
,
'timeout'
:
timeout
,
'instance_ids'
:
{
'instances'
:
[
i
[
'id'
]
for
i
in
success
+
error
+
timeout
],
'success'
:
[
i
[
'id'
]
for
i
in
success
],
'error'
:
[
i
[
'id'
]
for
i
in
error
],
'timeout'
:
[
i
[
'id'
]
for
i
in
timeout
]
}
}
if
timeout
:
results
[
'msg'
]
=
'Timeout waiting for all servers to delete'
elif
error
:
results
[
'msg'
]
=
'Failed to delete all servers'
if
'msg'
in
results
:
module
.
fail_json
(
**
results
)
else
:
module
.
exit_json
(
**
results
)
def
cloudservers
(
module
,
state
,
name
,
flavor
,
image
,
meta
,
key_name
,
files
,
wait
,
wait_timeout
,
disk_config
,
count
,
group
,
instance_ids
,
exact_count
,
networks
,
count_offset
):
cs
=
pyrax
.
cloudservers
cnw
=
pyrax
.
cloud_networks
servers
=
[]
# Add the group meta key
if
group
and
'group'
not
in
meta
:
meta
[
'group'
]
=
group
elif
'group'
in
meta
and
group
is
None
:
group
=
meta
[
'group'
]
# Check if the provided image is a UUID and if not, search for an
# appropriate image using human_id and name
if
image
:
try
:
UUID
(
image
)
except
ValueError
:
try
:
try
:
servers
=
[
pyrax
.
cloudservers
.
servers
.
create
(
name
=
name
,
image
=
cs
.
images
.
find
(
human_id
=
image
)
image
=
image
,
except
(
pyrax
.
exceptions
.
NotFound
,
flavor
=
flavor
,
pyrax
.
exceptions
.
NoUniqueMatch
):
key_name
=
key_name
,
try
:
meta
=
meta
,
image
=
cs
.
images
.
find
(
name
=
image
)
files
=
files
,
except
(
pyrax
.
exceptions
.
NotFound
,
disk_config
=
disk_config
)]
pyrax
.
exceptions
.
NoUniqueMatch
):
changed
=
True
module
.
fail_json
(
msg
=
'No matching image found (
%
s)'
%
except
Exception
,
e
:
image
)
module
.
fail_json
(
msg
=
'
%
s'
%
e
.
message
)
image
=
pyrax
.
utils
.
get_id
(
image
)
for
server
in
servers
:
# If requested, wait for server activation
# Check if the provided network is a UUID and if not, search for an
if
wait
:
# appropriate network using label
pyrax
.
utils
.
wait_until
(
server
,
'status'
,
(
'ACTIVE'
,
'ERROR'
),
nics
=
[]
interval
=
5
,
attempts
=
wait_timeout
/
5
)
if
networks
:
for
network
in
networks
:
# Get a fresh copy of the server details
try
:
server
.
get
()
UUID
(
network
)
if
server
.
status
==
'ACTIVE'
:
except
ValueError
:
instance
=
{
'id'
:
server
.
id
,
if
network
.
lower
()
==
'public'
:
'accessIPv4'
:
server
.
accessIPv4
,
nics
.
extend
(
cnw
.
get_server_networks
(
PUBLIC_NET_ID
))
'name'
:
server
.
name
,
elif
network
.
lower
()
==
'private'
:
'status'
:
server
.
status
}
nics
.
extend
(
cnw
.
get_server_networks
(
SERVICE_NET_ID
))
instances
.
append
(
instance
)
else
:
elif
server
.
status
==
'ERROR'
:
module
.
fail_json
(
msg
=
'
%
s failed to build'
%
server
.
id
)
elif
wait
:
# waiting took too long
module
.
fail_json
(
msg
=
'Timeout waiting on
%
s'
%
server
.
id
)
elif
state
in
(
'absent'
,
'deleted'
):
# See if we can find a server that matches our credentials
for
server
in
servers
:
if
server
.
name
==
name
:
if
int
(
server
.
flavor
[
'id'
])
==
int
(
flavor
)
and
\
server
.
image
[
'id'
]
==
image
and
\
server
.
metadata
==
meta
:
try
:
try
:
server
.
delete
()
network_obj
=
cnw
.
find_network_by_label
(
network
)
except
Exception
,
e
:
except
(
pyrax
.
exceptions
.
NetworkNotFound
,
module
.
fail_json
(
msg
=
e
.
message
)
pyrax
.
exceptions
.
NetworkLabelNotUnique
):
module
.
fail_json
(
msg
=
'No matching network found (
%
s)'
%
instance
=
{
'id'
:
server
.
id
,
network
)
'accessIPv4'
:
server
.
accessIPv4
,
else
:
'name'
:
server
.
name
,
nics
.
extend
(
cnw
.
get_server_networks
(
network_obj
))
'status'
:
'DELETING'
}
else
:
nics
.
extend
(
cnw
.
get_server_networks
(
network
))
# If requested, wait for server deletion
if
wait
:
# act on the state
try
:
if
state
==
'present'
:
pyrax
.
utils
.
wait_until
(
server
,
'status'
,
''
,
interval
=
5
,
for
arg
,
value
in
dict
(
name
=
name
,
flavor
=
flavor
,
attempts
=
wait_timeout
/
5
)
image
=
image
)
.
iteritems
():
# Get a fresh copy of the server details
if
not
value
:
server
.
get
()
module
.
fail_json
(
msg
=
'
%
s is required for the "rax" module'
%
except
Exception
,
e
:
arg
)
# In this case, an exception means the server is NotFound
instance
[
'status'
]
=
'DELETED'
# Idempotent ensurance of a specific count of servers
else
:
if
exact_count
is
not
False
:
# waiting took too long
# See if we can find servers that match our options
module
.
fail_json
(
msg
=
'Timeout waiting on delete
%
s (
%
s)'
%
(
server
.
id
,
server
.
status
))
if
group
is
None
:
module
.
fail_json
(
msg
=
'"group" must be provided when using '
instances
.
append
(
instance
)
'"exact_count"'
)
changed
=
True
else
:
numbers
=
set
()
module
.
exit_json
(
changed
=
changed
,
instances
=
instances
)
try
:
name
%
0
except
TypeError
,
e
:
if
e
.
message
.
startswith
(
'not all'
):
name
=
'
%
s
%%
d'
%
name
else
:
module
.
fail_json
(
msg
=
e
.
message
)
pattern
=
re
.
sub
(
r'
%
\d+[sd]'
,
r'(\d+)'
,
name
)
for
server
in
cs
.
servers
.
list
():
if
server
.
metadata
.
get
(
'group'
)
==
group
:
servers
.
append
(
server
)
match
=
re
.
search
(
pattern
,
server
.
name
)
if
match
:
number
=
int
(
match
.
group
(
1
))
numbers
.
add
(
number
)
number_range
=
xrange
(
count_offset
,
count_offset
+
count
)
available_numbers
=
list
(
set
(
number_range
)
.
difference
(
numbers
))
if
len
(
servers
)
>
count
:
state
=
'absent'
del
servers
[:
count
]
instance_ids
=
[]
for
server
in
servers
:
instance_ids
.
append
(
server
.
id
)
delete
(
module
,
instance_ids
,
wait
,
wait_timeout
)
elif
len
(
servers
)
<
count
:
names
=
[]
numbers_to_use
=
available_numbers
[:
count
-
len
(
servers
)]
for
number
in
numbers_to_use
:
names
.
append
(
name
%
number
)
else
:
module
.
exit_json
(
changed
=
False
,
action
=
None
,
instances
=
[],
success
=
[],
error
=
[],
timeout
=
[],
instance_ids
=
{
'instances'
:
[],
'success'
:
[],
'error'
:
[],
'timeout'
:
[]})
else
:
if
group
is
not
None
:
numbers
=
set
()
try
:
name
%
0
except
TypeError
,
e
:
if
e
.
message
.
startswith
(
'not all'
):
name
=
'
%
s
%%
d'
%
name
else
:
module
.
fail_json
(
msg
=
e
.
message
)
pattern
=
re
.
sub
(
r'
%
\d+[sd]'
,
r'(\d+)'
,
name
)
for
server
in
cs
.
servers
.
list
():
if
server
.
metadata
.
get
(
'group'
)
==
group
:
servers
.
append
(
server
)
match
=
re
.
search
(
pattern
,
server
.
name
)
if
match
:
number
=
int
(
match
.
group
(
1
))
numbers
.
add
(
number
)
number_range
=
xrange
(
count_offset
,
count_offset
+
count
+
len
(
numbers
))
available_numbers
=
list
(
set
(
number_range
)
.
difference
(
numbers
))
names
=
[]
numbers_to_use
=
available_numbers
[:
count
]
for
number
in
numbers_to_use
:
names
.
append
(
name
%
number
)
else
:
search_opts
=
{
'name'
:
name
,
'image'
:
image
,
'flavor'
:
flavor
}
servers
=
[]
for
server
in
cs
.
servers
.
list
(
search_opts
=
search_opts
):
if
server
.
metadata
!=
meta
:
continue
servers
.
append
(
server
)
if
len
(
servers
)
>=
count
:
instances
=
[]
for
server
in
servers
:
instances
.
append
(
pyrax_object_to_dict
(
server
))
instance_ids
=
[
i
[
'id'
]
for
i
in
instances
]
module
.
exit_json
(
changed
=
False
,
action
=
None
,
instances
=
instances
,
success
=
[],
error
=
[],
timeout
=
[],
instance_ids
=
{
'instances'
:
instance_ids
,
'success'
:
[],
'error'
:
[],
'timeout'
:
[]})
names
=
[
name
]
*
(
count
-
len
(
servers
))
create
(
module
,
names
,
flavor
,
image
,
meta
,
key_name
,
files
,
wait
,
wait_timeout
,
disk_config
,
group
,
nics
)
elif
state
==
'absent'
:
if
instance_ids
is
None
:
for
arg
,
value
in
dict
(
name
=
name
,
flavor
=
flavor
,
image
=
image
)
.
iteritems
():
if
not
value
:
module
.
fail_json
(
msg
=
'
%
s is required for the "rax" '
'module'
%
arg
)
search_opts
=
{
'name'
:
name
,
'image'
:
image
,
'flavor'
:
flavor
}
for
server
in
cs
.
servers
.
list
(
search_opts
=
search_opts
):
if
meta
!=
server
.
metadata
:
continue
servers
.
append
(
server
)
instance_ids
=
[]
for
server
in
servers
:
if
len
(
instance_ids
)
<
count
:
instance_ids
.
append
(
server
.
id
)
else
:
break
if
not
instance_ids
:
module
.
exit_json
(
changed
=
False
,
action
=
None
,
instances
=
[],
success
=
[],
error
=
[],
timeout
=
[],
instance_ids
=
{
'instances'
:
[],
'success'
:
[],
'error'
:
[],
'timeout'
:
[]})
delete
(
module
,
instance_ids
,
wait
,
wait_timeout
)
def
main
():
def
main
():
module
=
AnsibleModule
(
module
=
AnsibleModule
(
argument_spec
=
dict
(
argument_spec
=
dict
(
service
=
dict
(
default
=
'cloudservers'
,
choices
=
SUPPORTEDSERVICES
),
state
=
dict
(
default
=
'present'
,
choices
=
[
'active'
,
'present'
,
'deleted'
,
'absent'
]),
credentials
=
dict
(
aliases
=
[
'creds_file'
]),
api_key
=
dict
(),
api_key
=
dict
(),
count
=
dict
(
default
=
1
,
type
=
'int'
),
count_offset
=
dict
(
default
=
1
,
type
=
'int'
),
credentials
=
dict
(
aliases
=
[
'creds_file'
]),
disk_config
=
dict
(
default
=
'auto'
,
choices
=
[
'auto'
,
'manual'
]),
exact_count
=
dict
(
choices
=
BOOLEANS
,
default
=
False
,
type
=
'bool'
),
files
=
dict
(
type
=
'dict'
,
default
=
{}),
flavor
=
dict
(),
group
=
dict
(),
image
=
dict
(),
instance_ids
=
dict
(
type
=
'list'
),
key_name
=
dict
(
aliases
=
[
'keypair'
]),
meta
=
dict
(
type
=
'dict'
,
default
=
{}),
name
=
dict
(),
networks
=
dict
(
type
=
'list'
,
default
=
[
'public'
,
'private'
]),
region
=
dict
(),
service
=
dict
(),
state
=
dict
(
default
=
'present'
,
choices
=
[
'present'
,
'absent'
]),
username
=
dict
(),
username
=
dict
(),
name
=
dict
(),
wait
=
dict
(
choices
=
BOOLEANS
,
default
=
False
,
type
=
'bool'
),
flavor
=
dict
(),
wait_timeout
=
dict
(
default
=
300
),
image
=
dict
(),
),
disk_config
=
dict
(
default
=
'auto'
,
choices
=
[
'auto'
,
'manual'
]),
meta
=
dict
(
type
=
'dict'
,
default
=
{}),
key_name
=
dict
(
aliases
=
[
'keypair'
]),
files
=
dict
(
type
=
'dict'
,
default
=
{}),
region
=
dict
(),
wait
=
dict
(
type
=
'bool'
),
wait_timeout
=
dict
(
default
=
300
),
)
)
)
service
=
module
.
params
.
get
(
'service'
)
service
=
module
.
params
.
get
(
'service'
)
state
=
module
.
params
.
get
(
'state'
)
credentials
=
module
.
params
.
get
(
'credentials'
)
if
service
is
not
None
:
module
.
fail_json
(
msg
=
'The "service" attribute has been deprecated, '
'please remove "service: cloudservers" from your '
'playbook pertaining to the "rax" module'
)
api_key
=
module
.
params
.
get
(
'api_key'
)
api_key
=
module
.
params
.
get
(
'api_key'
)
username
=
module
.
params
.
get
(
'username'
)
count
=
module
.
params
.
get
(
'count'
)
name
=
module
.
params
.
get
(
'name'
)
count_offset
=
module
.
params
.
get
(
'count_offset'
)
credentials
=
module
.
params
.
get
(
'credentials'
)
disk_config
=
module
.
params
.
get
(
'disk_config'
)
.
upper
()
exact_count
=
module
.
params
.
get
(
'exact_count'
,
False
)
files
=
module
.
params
.
get
(
'files'
)
flavor
=
module
.
params
.
get
(
'flavor'
)
flavor
=
module
.
params
.
get
(
'flavor'
)
group
=
module
.
params
.
get
(
'group'
)
image
=
module
.
params
.
get
(
'image'
)
image
=
module
.
params
.
get
(
'image'
)
meta
=
module
.
params
.
get
(
'meta
'
)
instance_ids
=
module
.
params
.
get
(
'instance_ids
'
)
key_name
=
module
.
params
.
get
(
'key_name'
)
key_name
=
module
.
params
.
get
(
'key_name'
)
files
=
module
.
params
.
get
(
'files'
)
meta
=
module
.
params
.
get
(
'meta'
)
name
=
module
.
params
.
get
(
'name'
)
networks
=
module
.
params
.
get
(
'networks'
)
region
=
module
.
params
.
get
(
'region'
)
region
=
module
.
params
.
get
(
'region'
)
state
=
module
.
params
.
get
(
'state'
)
username
=
module
.
params
.
get
(
'username'
)
wait
=
module
.
params
.
get
(
'wait'
)
wait
=
module
.
params
.
get
(
'wait'
)
wait_timeout
=
int
(
module
.
params
.
get
(
'wait_timeout'
))
wait_timeout
=
int
(
module
.
params
.
get
(
'wait_timeout'
))
disk_config
=
module
.
params
.
get
(
'disk_config'
)
.
upper
()
# Setup the credentials and region
# Setup the credentials and region
try
:
try
:
username
=
username
or
os
.
environ
.
get
(
'RAX_USERNAME'
)
username
=
username
or
os
.
environ
.
get
(
'RAX_USERNAME'
)
api_key
=
api_key
or
os
.
environ
.
get
(
'RAX_API_KEY'
)
api_key
=
api_key
or
os
.
environ
.
get
(
'RAX_API_KEY'
)
credentials
=
credentials
or
os
.
environ
.
get
(
'RAX_CREDENTIALS'
)
or
\
credentials
=
(
credentials
or
os
.
environ
.
get
(
'RAX_CREDENTIALS'
)
or
os
.
environ
.
get
(
'RAX_CREDS_FILE'
)
os
.
environ
.
get
(
'RAX_CREDS_FILE'
)
)
region
=
region
or
os
.
environ
.
get
(
'RAX_REGION'
)
region
=
region
or
os
.
environ
.
get
(
'RAX_REGION'
)
except
KeyError
,
e
:
except
KeyError
,
e
:
module
.
fail_json
(
msg
=
'Unable to load
%
s'
%
e
.
message
)
module
.
fail_json
(
msg
=
'Unable to load
%
s'
%
e
.
message
)
# setup the auth
# setup the auth
try
:
try
:
pyrax
.
set_setting
(
"identity_type"
,
"rackspace"
)
pyrax
.
set_setting
(
'identity_type'
,
'rackspace'
)
if
api_key
and
username
:
if
api_key
and
username
:
pyrax
.
set_credentials
(
username
,
api_key
=
api_key
,
region
=
region
)
pyrax
.
set_credentials
(
username
,
api_key
=
api_key
,
region
=
region
)
elif
credentials
:
elif
credentials
:
...
@@ -298,19 +625,14 @@ def main():
...
@@ -298,19 +625,14 @@ def main():
else
:
else
:
raise
Exception
(
'No credentials supplied!'
)
raise
Exception
(
'No credentials supplied!'
)
except
Exception
,
e
:
except
Exception
,
e
:
module
.
fail_json
(
msg
=
'
%
s'
%
e
.
message
)
module
.
fail_json
(
msg
=
'
%
s'
%
e
.
message
)
# Act based on service
cloudservers
(
module
,
state
,
name
,
flavor
,
image
,
meta
,
key_name
,
files
,
if
service
==
'cloudservers'
:
wait
,
wait_timeout
,
disk_config
,
count
,
group
,
cloudservers
(
module
,
state
,
name
,
flavor
,
image
,
meta
,
key_name
,
files
,
instance_ids
,
exact_count
,
networks
,
count_offset
)
wait
,
wait_timeout
,
disk_config
)
elif
service
in
[
'cloudfiles'
,
'cloud_blockstorage'
,
'cloud_databases'
,
'cloud_loadbalancers'
]:
module
.
fail_json
(
msg
=
'Service
%
s is not supported at this time'
%
service
)
# this is magic, see lib/ansible/module_common.py
from
ansible.module_utils.basic
import
*
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
### invoke the module
main
()
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment