fix restructuredtext formatting in docstrings that show up in the developer guide
blueprint sphinx-doc-cleanup bug 945160 - Correct parameter declarations, list formatting, cross-references, etc. - We don't need "let" in generate_autodoc_index.sh since we aren't doing math. - Change conf.py to not prefix class and function names with full namespace in generated output to save width on the screen. Change-Id: I9adc8681951913fd291d03e7142146e9d46841df
This commit is contained in:
parent
5f9cee0c9c
commit
b1de27f68a
@ -15,11 +15,12 @@ do
|
||||
# and make sure to emit that many '=' under
|
||||
# it to avoid heading format errors
|
||||
# in Sphinx.
|
||||
let heading_len=$(echo "$heading" | wc -c)
|
||||
heading_len=$(echo "$heading" | wc -c)
|
||||
underline=$(head -c $heading_len < /dev/zero | tr '\0' '=')
|
||||
( cat <<EOF
|
||||
${heading}
|
||||
${underline}
|
||||
|
||||
.. automodule:: ${x}
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
@ -92,7 +92,7 @@ exclude_trees = []
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
add_module_names = False
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
|
@ -144,17 +144,16 @@ def _get_marker_param(request):
|
||||
|
||||
|
||||
def limited(items, request, max_limit=FLAGS.osapi_max_limit):
|
||||
"""
|
||||
Return a slice of items according to requested offset and limit.
|
||||
"""Return a slice of items according to requested offset and limit.
|
||||
|
||||
@param items: A sliceable entity
|
||||
@param request: `wsgi.Request` possibly containing 'offset' and 'limit'
|
||||
:param items: A sliceable entity
|
||||
:param request: ``wsgi.Request`` possibly containing 'offset' and 'limit'
|
||||
GET variables. 'offset' is where to start in the list,
|
||||
and 'limit' is the maximum number of items to return. If
|
||||
'limit' is not specified, 0, or > max_limit, we default
|
||||
to max_limit. Negative values for either offset or limit
|
||||
will cause exc.HTTPBadRequest() exceptions to be raised.
|
||||
@kwarg max_limit: The maximum number of items to return from 'items'
|
||||
:kwarg max_limit: The maximum number of items to return from 'items'
|
||||
"""
|
||||
try:
|
||||
offset = int(request.GET.get('offset', 0))
|
||||
@ -309,15 +308,15 @@ def get_nw_info_for_instance(context, instance):
|
||||
|
||||
|
||||
def get_networks_for_instance(context, instance):
|
||||
"""Returns a prepared nw_info list for passing into the view
|
||||
builders
|
||||
"""Returns a prepared nw_info list for passing into the view builders
|
||||
|
||||
We end up with a data structure like:
|
||||
{'public': {'ips': [{'addr': '10.0.0.1', 'version': 4},
|
||||
{'addr': '2001::1', 'version': 6}],
|
||||
'floating_ips': [{'addr': '172.16.0.1', 'version': 4},
|
||||
{'addr': '172.16.2.1', 'version': 4}]},
|
||||
...}
|
||||
We end up with a data structure like::
|
||||
|
||||
{'public': {'ips': [{'addr': '10.0.0.1', 'version': 4},
|
||||
{'addr': '2001::1', 'version': 6}],
|
||||
'floating_ips': [{'addr': '172.16.0.1', 'version': 4},
|
||||
{'addr': '172.16.2.1', 'version': 4}]},
|
||||
...}
|
||||
"""
|
||||
nw_info = get_nw_info_for_instance(context, instance)
|
||||
return get_networks_for_instance_from_nw_info(nw_info)
|
||||
|
@ -16,11 +16,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
The Flavor extra data extension
|
||||
"""The Flavor extra data extension
|
||||
|
||||
Openstack API version 1.1 lists "name", "ram", "disk", "vcpus" as flavor
|
||||
attributes. This extension adds to that list:
|
||||
OS-FLV-EXT-DATA:ephemeral
|
||||
|
||||
- OS-FLV-EXT-DATA:ephemeral
|
||||
"""
|
||||
|
||||
from nova import exception
|
||||
|
@ -216,7 +216,9 @@ class HostController(object):
|
||||
:param context: security context
|
||||
:param host: hostname
|
||||
:returns: expected to use HostShowTemplate.
|
||||
ex. {'host': {'resource':D},..}
|
||||
ex.::
|
||||
|
||||
{'host': {'resource':D},..}
|
||||
D: {'host': 'hostname','project': 'admin',
|
||||
'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}
|
||||
"""
|
||||
|
@ -382,8 +382,8 @@ class WsgiLimiter(object):
|
||||
"""
|
||||
Rate-limit checking from a WSGI application. Uses an in-memory `Limiter`.
|
||||
|
||||
To use:
|
||||
POST /<username> with JSON data such as:
|
||||
To use, POST ``/<username>`` with JSON data such as::
|
||||
|
||||
{
|
||||
"verb" : GET,
|
||||
"path" : "/servers"
|
||||
|
@ -114,10 +114,11 @@ def validate_user_data(user_data):
|
||||
def validate(args, validator):
|
||||
"""Validate values of args against validators in validator.
|
||||
|
||||
args Dict of values to be validated.
|
||||
validator A dict where the keys map to keys in args
|
||||
and the values are validators.
|
||||
Applies each validator to args[key]
|
||||
:param args: Dict of values to be validated.
|
||||
:param validator: A dict where the keys map to keys in args
|
||||
and the values are validators.
|
||||
Applies each validator to ``args[key]``
|
||||
:returns: True if validation succeeds. Otherwise False.
|
||||
|
||||
A validator should be a callable which accepts 1 argument and which
|
||||
returns True if the argument passes validation. False otherwise.
|
||||
@ -126,7 +127,6 @@ def validate(args, validator):
|
||||
|
||||
Only validates keys which show up in both args and validator.
|
||||
|
||||
returns True if validation succeeds. Otherwise False.
|
||||
"""
|
||||
|
||||
for key in validator:
|
||||
|
@ -244,9 +244,9 @@ class FakeLDAP(object):
|
||||
def modify_s(self, dn, attrs):
|
||||
"""Modify the object at dn using the attribute list.
|
||||
|
||||
Args:
|
||||
dn -- a dn
|
||||
attrs -- a list of tuples in the following form:
|
||||
:param dn: a dn
|
||||
:param attrs: a list of tuples in the following form::
|
||||
|
||||
([MOD_ADD | MOD_DELETE | MOD_REPACE], attribute, value)
|
||||
|
||||
"""
|
||||
|
@ -129,11 +129,17 @@ class User(AuthBase):
|
||||
"""Object representing a user
|
||||
|
||||
The following attributes are defined:
|
||||
:id: A system identifier for the user. A string (for LDAP)
|
||||
:name: The user name, potentially in some more friendly format
|
||||
:access: The 'username' for EC2 authentication
|
||||
:secret: The 'password' for EC2 authenticatoin
|
||||
:admin: ???
|
||||
|
||||
``id``
|
||||
A system identifier for the user. A string (for LDAP)
|
||||
``name``
|
||||
The user name, potentially in some more friendly format
|
||||
``access``
|
||||
The 'username' for EC2 authentication
|
||||
``secret``
|
||||
The 'password' for EC2 authenticatoin
|
||||
``admin``
|
||||
???
|
||||
"""
|
||||
|
||||
def __init__(self, id, name, access, secret, admin):
|
||||
@ -259,35 +265,35 @@ class AuthManager(object):
|
||||
a project with the same name as the user. This way, older tools
|
||||
that have no project knowledge will still work.
|
||||
|
||||
@type access: str
|
||||
@param access: Access key for user in the form "access:project".
|
||||
:type access: str
|
||||
:param access: Access key for user in the form "access:project".
|
||||
|
||||
@type signature: str
|
||||
@param signature: Signature of the request.
|
||||
:type signature: str
|
||||
:param signature: Signature of the request.
|
||||
|
||||
@type params: list of str
|
||||
@param params: Web paramaters used for the signature.
|
||||
:type params: list of str
|
||||
:param params: Web paramaters used for the signature.
|
||||
|
||||
@type verb: str
|
||||
@param verb: Web request verb ('GET' or 'POST').
|
||||
:type verb: str
|
||||
:param verb: Web request verb ('GET' or 'POST').
|
||||
|
||||
@type server_string: str
|
||||
@param server_string: Web request server string.
|
||||
:type server_string: str
|
||||
:param server_string: Web request server string.
|
||||
|
||||
@type path: str
|
||||
@param path: Web request path.
|
||||
:type path: str
|
||||
:param path: Web request path.
|
||||
|
||||
@type check_type: str
|
||||
@param check_type: Type of signature to check. 'ec2' for EC2, 's3' for
|
||||
:type check_type: str
|
||||
:param check_type: Type of signature to check. 'ec2' for EC2, 's3' for
|
||||
S3. Any other value will cause signature not to be
|
||||
checked.
|
||||
|
||||
@type headers: list
|
||||
@param headers: HTTP headers passed with the request (only needed for
|
||||
:type headers: list
|
||||
:param headers: HTTP headers passed with the request (only needed for
|
||||
s3 signature checks)
|
||||
|
||||
@rtype: tuple (User, Project)
|
||||
@return: User and project that the request represents.
|
||||
:rtype: tuple (User, Project)
|
||||
:return: User and project that the request represents.
|
||||
"""
|
||||
# TODO(vish): check for valid timestamp
|
||||
(access_key, _sep, project_id) = access.partition(':')
|
||||
@ -365,11 +371,11 @@ class AuthManager(object):
|
||||
def is_superuser(self, user):
|
||||
"""Checks for superuser status, allowing user to bypass authorization
|
||||
|
||||
@type user: User or uid
|
||||
@param user: User to check.
|
||||
:type user: User or uid
|
||||
:param user: User to check.
|
||||
|
||||
@rtype: bool
|
||||
@return: True for superuser.
|
||||
:rtype: bool
|
||||
:return: True for superuser.
|
||||
"""
|
||||
if not isinstance(user, User):
|
||||
user = self.get_user(user)
|
||||
@ -383,11 +389,11 @@ class AuthManager(object):
|
||||
def is_admin(self, user):
|
||||
"""Checks for admin status, allowing user to access all projects
|
||||
|
||||
@type user: User or uid
|
||||
@param user: User to check.
|
||||
:type user: User or uid
|
||||
:param user: User to check.
|
||||
|
||||
@rtype: bool
|
||||
@return: True for admin.
|
||||
:rtype: bool
|
||||
:return: True for admin.
|
||||
"""
|
||||
if not isinstance(user, User):
|
||||
user = self.get_user(user)
|
||||
@ -429,17 +435,17 @@ class AuthManager(object):
|
||||
see if the user is the project_manager of the specified project. It
|
||||
is the same as calling is_project_manager(user, project).
|
||||
|
||||
@type user: User or uid
|
||||
@param user: User to check.
|
||||
:type user: User or uid
|
||||
:param user: User to check.
|
||||
|
||||
@type role: str
|
||||
@param role: Role to check.
|
||||
:type role: str
|
||||
:param role: Role to check.
|
||||
|
||||
@type project: Project or project_id
|
||||
@param project: Project in which to look for local role.
|
||||
:type project: Project or project_id
|
||||
:param project: Project in which to look for local role.
|
||||
|
||||
@rtype: bool
|
||||
@return: True if the user has the role.
|
||||
:rtype: bool
|
||||
:return: True if the user has the role.
|
||||
"""
|
||||
if role == 'projectmanager':
|
||||
if not project:
|
||||
@ -468,14 +474,14 @@ class AuthManager(object):
|
||||
|
||||
The 'projectmanager' role is special and can't be added or removed.
|
||||
|
||||
@type user: User or uid
|
||||
@param user: User to which to add role.
|
||||
:type user: User or uid
|
||||
:param user: User to which to add role.
|
||||
|
||||
@type role: str
|
||||
@param role: Role to add.
|
||||
:type role: str
|
||||
:param role: Role to add.
|
||||
|
||||
@type project: Project or project_id
|
||||
@param project: Project in which to add local role.
|
||||
:type project: Project or project_id
|
||||
:param project: Project in which to add local role.
|
||||
"""
|
||||
if role not in FLAGS.allowed_roles:
|
||||
raise exception.UserRoleNotFound(role_id=role)
|
||||
@ -501,14 +507,14 @@ class AuthManager(object):
|
||||
|
||||
The 'projectmanager' role is special and can't be added or removed.
|
||||
|
||||
@type user: User or uid
|
||||
@param user: User from which to remove role.
|
||||
:type user: User or uid
|
||||
:param user: User from which to remove role.
|
||||
|
||||
@type role: str
|
||||
@param role: Role to remove.
|
||||
:type role: str
|
||||
:param role: Role to remove.
|
||||
|
||||
@type project: Project or project_id
|
||||
@param project: Project in which to remove local role.
|
||||
:type project: Project or project_id
|
||||
:param project: Project in which to remove local role.
|
||||
"""
|
||||
uid = User.safe_id(user)
|
||||
pid = Project.safe_id(project)
|
||||
@ -563,23 +569,23 @@ class AuthManager(object):
|
||||
member_users=None):
|
||||
"""Create a project
|
||||
|
||||
@type name: str
|
||||
@param name: Name of the project to create. The name will also be
|
||||
:type name: str
|
||||
:param name: Name of the project to create. The name will also be
|
||||
used as the project id.
|
||||
|
||||
@type manager_user: User or uid
|
||||
@param manager_user: This user will be the project manager.
|
||||
:type manager_user: User or uid
|
||||
:param manager_user: This user will be the project manager.
|
||||
|
||||
@type description: str
|
||||
@param project: Description of the project. If no description is
|
||||
:type description: str
|
||||
:param project: Description of the project. If no description is
|
||||
specified, the name of the project will be used.
|
||||
|
||||
@type member_users: list of User or uid
|
||||
@param: Initial project members. The project manager will always be
|
||||
:type member_users: list of User or uid
|
||||
:param: Initial project members. The project manager will always be
|
||||
added as a member, even if he isn't specified in this list.
|
||||
|
||||
@rtype: Project
|
||||
@return: The new project.
|
||||
:rtype: Project
|
||||
:return: The new project.
|
||||
"""
|
||||
if member_users:
|
||||
member_users = [User.safe_id(u) for u in member_users]
|
||||
@ -597,14 +603,14 @@ class AuthManager(object):
|
||||
def modify_project(self, project, manager_user=None, description=None):
|
||||
"""Modify a project
|
||||
|
||||
@type name: Project or project_id
|
||||
@param project: The project to modify.
|
||||
:type name: Project or project_id
|
||||
:param project: The project to modify.
|
||||
|
||||
@type manager_user: User or uid
|
||||
@param manager_user: This user will be the new project manager.
|
||||
:type manager_user: User or uid
|
||||
:param manager_user: This user will be the new project manager.
|
||||
|
||||
@type description: str
|
||||
@param project: This will be the new description of the project.
|
||||
:type description: str
|
||||
:param project: This will be the new description of the project.
|
||||
|
||||
"""
|
||||
LOG.audit(_("modifying project %s"), Project.safe_id(project))
|
||||
@ -648,12 +654,12 @@ class AuthManager(object):
|
||||
def get_project_vpn_data(project):
|
||||
"""Gets vpn ip and port for project
|
||||
|
||||
@type project: Project or project_id
|
||||
@param project: Project from which to get associated vpn data
|
||||
:type project: Project or project_id
|
||||
:param project: Project from which to get associated vpn data
|
||||
|
||||
@rvalue: tuple of (str, str)
|
||||
@return: A tuple containing (ip, port) or None, None if vpn has
|
||||
not been allocated for user.
|
||||
:rvalue: tuple of (str, str)
|
||||
:return: A tuple containing (ip, port) or None, None if vpn has
|
||||
not been allocated for user.
|
||||
"""
|
||||
|
||||
networks = db.project_get_networks(context.get_admin_context(),
|
||||
@ -699,24 +705,24 @@ class AuthManager(object):
|
||||
def create_user(self, name, access=None, secret=None, admin=False):
|
||||
"""Creates a user
|
||||
|
||||
@type name: str
|
||||
@param name: Name of the user to create.
|
||||
:type name: str
|
||||
:param name: Name of the user to create.
|
||||
|
||||
@type access: str
|
||||
@param access: Access Key (defaults to a random uuid)
|
||||
:type access: str
|
||||
:param access: Access Key (defaults to a random uuid)
|
||||
|
||||
@type secret: str
|
||||
@param secret: Secret Key (defaults to a random uuid)
|
||||
:type secret: str
|
||||
:param secret: Secret Key (defaults to a random uuid)
|
||||
|
||||
@type admin: bool
|
||||
@param admin: Whether to set the admin flag. The admin flag gives
|
||||
:type admin: bool
|
||||
:param admin: Whether to set the admin flag. The admin flag gives
|
||||
superuser status regardless of roles specified for the user.
|
||||
|
||||
@type create_project: bool
|
||||
@param: Whether to create a project for the user with the same name.
|
||||
:type create_project: bool
|
||||
:param: Whether to create a project for the user with the same name.
|
||||
|
||||
@rtype: User
|
||||
@return: The new user.
|
||||
:rtype: User
|
||||
:return: The new user.
|
||||
"""
|
||||
if access is None:
|
||||
access = str(uuid.uuid4())
|
||||
|
@ -17,10 +17,11 @@
|
||||
Cert manager manages x509 certificates.
|
||||
|
||||
**Related Flags**
|
||||
|
||||
:cert_topic: What :mod:`rpc` topic to listen to (default: `cert`).
|
||||
:cert_manager: The module name of a class derived from
|
||||
:class:`manager.Manager` (default:
|
||||
:class:`nova.cert.manager.Manager`).
|
||||
:class:`manager.Manager` (default:
|
||||
:class:`nova.cert.manager.Manager`).
|
||||
"""
|
||||
|
||||
import base64
|
||||
|
@ -49,49 +49,64 @@ def enforce(match_list, target_dict, credentials_dict):
|
||||
"""Enforces authorization of some rules against credentials.
|
||||
|
||||
:param match_list: nested tuples of data to match against
|
||||
The basic brain supports three types of match lists:
|
||||
1) rules
|
||||
looks like: ('rule:compute:get_instance',)
|
||||
Retrieves the named rule from the rules dict and recursively
|
||||
checks against the contents of the rule.
|
||||
2) roles
|
||||
looks like: ('role:compute:admin',)
|
||||
Matches if the specified role is in credentials_dict['roles'].
|
||||
3) generic
|
||||
('tenant_id:%(tenant_id)s',)
|
||||
Substitutes values from the target dict into the match using
|
||||
the % operator and matches them against the creds dict.
|
||||
|
||||
Combining rules:
|
||||
The brain returns True if any of the outer tuple of rules match
|
||||
and also True if all of the inner tuples match. You can use this to
|
||||
perform simple boolean logic. For example, the following rule would
|
||||
return True if the creds contain the role 'admin' OR the if the
|
||||
tenant_id matches the target dict AND the the creds contains the
|
||||
role 'compute_sysadmin':
|
||||
The basic brain supports three types of match lists:
|
||||
|
||||
{
|
||||
"rule:combined": (
|
||||
'role:admin',
|
||||
('tenant_id:%(tenant_id)s', 'role:compute_sysadmin')
|
||||
)
|
||||
}
|
||||
1) rules
|
||||
|
||||
looks like: ``('rule:compute:get_instance',)``
|
||||
|
||||
Note that rule and role are reserved words in the credentials match, so
|
||||
you can't match against properties with those names. Custom brains may
|
||||
also add new reserved words. For example, the HttpBrain adds http as a
|
||||
reserved word.
|
||||
Retrieves the named rule from the rules dict and recursively
|
||||
checks against the contents of the rule.
|
||||
|
||||
2) roles
|
||||
|
||||
looks like: ``('role:compute:admin',)``
|
||||
|
||||
Matches if the specified role is in credentials_dict['roles'].
|
||||
|
||||
3) generic
|
||||
|
||||
looks like: ``('tenant_id:%(tenant_id)s',)``
|
||||
|
||||
Substitutes values from the target dict into the match using
|
||||
the % operator and matches them against the creds dict.
|
||||
|
||||
Combining rules:
|
||||
|
||||
The brain returns True if any of the outer tuple of rules
|
||||
match and also True if all of the inner tuples match. You
|
||||
can use this to perform simple boolean logic. For
|
||||
example, the following rule would return True if the creds
|
||||
contain the role 'admin' OR the if the tenant_id matches
|
||||
the target dict AND the the creds contains the role
|
||||
'compute_sysadmin':
|
||||
|
||||
::
|
||||
|
||||
{
|
||||
"rule:combined": (
|
||||
'role:admin',
|
||||
('tenant_id:%(tenant_id)s', 'role:compute_sysadmin')
|
||||
)
|
||||
}
|
||||
|
||||
Note that rule and role are reserved words in the credentials match, so
|
||||
you can't match against properties with those names. Custom brains may
|
||||
also add new reserved words. For example, the HttpBrain adds http as a
|
||||
reserved word.
|
||||
|
||||
:param target_dict: dict of object properties
|
||||
Target dicts contain as much information as we can about the object being
|
||||
operated on.
|
||||
|
||||
Target dicts contain as much information as we can about the object being
|
||||
operated on.
|
||||
|
||||
:param credentials_dict: dict of actor properties
|
||||
Credentials dicts contain as much information as we can about the user
|
||||
performing the action.
|
||||
|
||||
:raises NotAuthorized if the check fails
|
||||
Credentials dicts contain as much information as we can about the user
|
||||
performing the action.
|
||||
|
||||
:raises NotAuthorized: if the check fails
|
||||
|
||||
"""
|
||||
global _BRAIN
|
||||
|
@ -169,7 +169,7 @@ def handle_flagfiles(args, tempdir=None):
|
||||
def handle_flagfiles_managed(args):
|
||||
'''A context manager for handle_flagfiles() which removes temp files.
|
||||
|
||||
For use with the 'with' statement, i.e.
|
||||
For use with the 'with' statement, i.e.::
|
||||
|
||||
with handle_flagfiles_managed(args) as args:
|
||||
# Do stuff
|
||||
|
@ -211,21 +211,25 @@ class VIF(Model):
|
||||
for floating_ip in fixed_ip['floating_ips']]
|
||||
|
||||
def labeled_ips(self):
|
||||
""" returns the list of all IPs in this flat structure:
|
||||
{'network_label': 'my_network',
|
||||
'network_id': 'n8v29837fn234782f08fjxk3ofhb84',
|
||||
'ips': [{'address': '123.123.123.123',
|
||||
'version': 4,
|
||||
'type: 'fixed',
|
||||
'meta': {...}},
|
||||
{'address': '124.124.124.124',
|
||||
'version': 4,
|
||||
'type': 'floating',
|
||||
'meta': {...}},
|
||||
{'address': 'fe80::4',
|
||||
'version': 6,
|
||||
'type': 'fixed',
|
||||
'meta': {...}}]"""
|
||||
"""Returns the list of all IPs
|
||||
|
||||
The return value looks like this flat structure::
|
||||
|
||||
{'network_label': 'my_network',
|
||||
'network_id': 'n8v29837fn234782f08fjxk3ofhb84',
|
||||
'ips': [{'address': '123.123.123.123',
|
||||
'version': 4,
|
||||
'type: 'fixed',
|
||||
'meta': {...}},
|
||||
{'address': '124.124.124.124',
|
||||
'version': 4,
|
||||
'type': 'floating',
|
||||
'meta': {...}},
|
||||
{'address': 'fe80::4',
|
||||
'version': 6,
|
||||
'type': 'fixed',
|
||||
'meta': {...}}]
|
||||
"""
|
||||
if self['network']:
|
||||
# remove unecessary fields on fixed_ips
|
||||
ips = [IP(**ensure_string_keys(ip)) for ip in self.fixed_ips()]
|
||||
|
@ -79,35 +79,35 @@ def publisher_id(service, host=None):
|
||||
|
||||
|
||||
def notify(publisher_id, event_type, priority, payload):
|
||||
"""
|
||||
Sends a notification using the specified driver
|
||||
"""Sends a notification using the specified driver
|
||||
|
||||
Notify parameters:
|
||||
|
||||
publisher_id - the source worker_type.host of the message
|
||||
event_type - the literal type of event (ex. Instance Creation)
|
||||
priority - patterned after the enumeration of Python logging levels in
|
||||
the set (DEBUG, WARN, INFO, ERROR, CRITICAL)
|
||||
payload - A python dictionary of attributes
|
||||
:param publisher_id: the source worker_type.host of the message
|
||||
:param event_type: the literal type of event (ex. Instance Creation)
|
||||
:param priority: patterned after the enumeration of Python logging
|
||||
levels in the set (DEBUG, WARN, INFO, ERROR, CRITICAL)
|
||||
:param payload: A python dictionary of attributes
|
||||
|
||||
Outgoing message format includes the above parameters, and appends the
|
||||
following:
|
||||
|
||||
message_id - a UUID representing the id for this notification
|
||||
timestamp - the GMT timestamp the notification was sent at
|
||||
message_id
|
||||
a UUID representing the id for this notification
|
||||
|
||||
timestamp
|
||||
the GMT timestamp the notification was sent at
|
||||
|
||||
The composite message will be constructed as a dictionary of the above
|
||||
attributes, which will then be sent via the transport mechanism defined
|
||||
by the driver.
|
||||
|
||||
Message example:
|
||||
Message example::
|
||||
|
||||
{'message_id': str(uuid.uuid4()),
|
||||
'publisher_id': 'compute.host1',
|
||||
'timestamp': utils.utcnow(),
|
||||
'priority': 'WARN',
|
||||
'event_type': 'compute.create_instance',
|
||||
'payload': {'instance_id': 12, ... }}
|
||||
{'message_id': str(uuid.uuid4()),
|
||||
'publisher_id': 'compute.host1',
|
||||
'timestamp': utils.utcnow(),
|
||||
'priority': 'WARN',
|
||||
'event_type': 'compute.create_instance',
|
||||
'payload': {'instance_id': 12, ... }}
|
||||
|
||||
"""
|
||||
if priority not in log_levels:
|
||||
|
@ -24,7 +24,7 @@ run something locally that was once running on S3.
|
||||
|
||||
We don't support all the features of S3, but it does work with the
|
||||
standard S3 client for the most basic semantics. To use the standard
|
||||
S3 client with this module:
|
||||
S3 client with this module::
|
||||
|
||||
c = S3.AWSAuthConnection("", "", server="localhost", port=8888,
|
||||
is_secure=False)
|
||||
|
@ -17,7 +17,9 @@
|
||||
r"""
|
||||
Configuration options which may be set on the command line or in config files.
|
||||
|
||||
The schema for each option is defined using the Opt sub-classes e.g.
|
||||
The schema for each option is defined using the Opt sub-classes, e.g.:
|
||||
|
||||
::
|
||||
|
||||
common_opts = [
|
||||
cfg.StrOpt('bind_host',
|
||||
@ -28,7 +30,7 @@ The schema for each option is defined using the Opt sub-classes e.g.
|
||||
help='Port number to listen on')
|
||||
]
|
||||
|
||||
Options can be strings, integers, floats, booleans, lists or 'multi strings':
|
||||
Options can be strings, integers, floats, booleans, lists or 'multi strings'::
|
||||
|
||||
enabled_apis_opt = cfg.ListOpt('enabled_apis',
|
||||
default=['ec2', 'osapi_compute'],
|
||||
@ -41,7 +43,7 @@ Options can be strings, integers, floats, booleans, lists or 'multi strings':
|
||||
default=DEFAULT_EXTENSIONS)
|
||||
|
||||
Option schemas are registered with with the config manager at runtime, but
|
||||
before the option is referenced:
|
||||
before the option is referenced::
|
||||
|
||||
class ExtensionManager(object):
|
||||
|
||||
@ -57,7 +59,7 @@ before the option is referenced:
|
||||
....
|
||||
|
||||
A common usage pattern is for each option schema to be defined in the module or
|
||||
class which uses the option:
|
||||
class which uses the option::
|
||||
|
||||
opts = ...
|
||||
|
||||
@ -72,7 +74,7 @@ class which uses the option:
|
||||
|
||||
An option may optionally be made available via the command line. Such options
|
||||
must registered with the config manager before the command line is parsed (for
|
||||
the purposes of --help and CLI arg validation):
|
||||
the purposes of --help and CLI arg validation)::
|
||||
|
||||
cli_opts = [
|
||||
cfg.BoolOpt('verbose',
|
||||
@ -88,7 +90,7 @@ the purposes of --help and CLI arg validation):
|
||||
def add_common_opts(conf):
|
||||
conf.register_cli_opts(cli_opts)
|
||||
|
||||
The config manager has a single CLI option defined by default, --config-file:
|
||||
The config manager has a single CLI option defined by default, --config-file::
|
||||
|
||||
class ConfigOpts(object):
|
||||
|
||||
@ -101,7 +103,7 @@ The config manager has a single CLI option defined by default, --config-file:
|
||||
|
||||
Option values are parsed from any supplied config files using SafeConfigParser.
|
||||
If none are specified, a default set is used e.g. glance-api.conf and
|
||||
glance-common.conf:
|
||||
glance-common.conf::
|
||||
|
||||
glance-api.conf:
|
||||
[DEFAULT]
|
||||
@ -116,7 +118,7 @@ are parsed in order, with values in later files overriding those in earlier
|
||||
files.
|
||||
|
||||
The parsing of CLI args and config files is initiated by invoking the config
|
||||
manager e.g.
|
||||
manager e.g.::
|
||||
|
||||
conf = ConfigOpts()
|
||||
conf.register_opt(BoolOpt('verbose', ...))
|
||||
@ -124,7 +126,7 @@ manager e.g.
|
||||
if conf.verbose:
|
||||
...
|
||||
|
||||
Options can be registered as belonging to a group:
|
||||
Options can be registered as belonging to a group::
|
||||
|
||||
rabbit_group = cfg.OptionGroup(name='rabbit',
|
||||
title='RabbitMQ options')
|
||||
@ -143,7 +145,7 @@ Options can be registered as belonging to a group:
|
||||
conf.register_opt(rabbit_port_opt, group='rabbit')
|
||||
|
||||
If no group is specified, options belong to the 'DEFAULT' section of config
|
||||
files:
|
||||
files::
|
||||
|
||||
glance-api.conf:
|
||||
[DEFAULT]
|
||||
@ -158,13 +160,14 @@ files:
|
||||
password = guest
|
||||
virtual_host = /
|
||||
|
||||
Command-line options in a group are automatically prefixed with the group name:
|
||||
Command-line options in a group are automatically prefixed with the
|
||||
group name::
|
||||
|
||||
--rabbit-host localhost --rabbit-port 9999
|
||||
|
||||
Option values in the default group are referenced as attributes/properties on
|
||||
the config manager; groups are also attributes on the config manager, with
|
||||
attributes for each of the options associated with the group:
|
||||
attributes for each of the options associated with the group::
|
||||
|
||||
server.start(app, conf.bind_port, conf.bind_host, conf)
|
||||
|
||||
@ -173,7 +176,7 @@ attributes for each of the options associated with the group:
|
||||
port=conf.rabbit.port,
|
||||
...)
|
||||
|
||||
Option values may reference other values using PEP 292 string substitution:
|
||||
Option values may reference other values using PEP 292 string substitution::
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('state_path',
|
||||
@ -191,15 +194,15 @@ Note that interpolation can be avoided by using '$$'.
|
||||
|
||||
For command line utilities that dispatch to other command line utilities, the
|
||||
disable_interspersed_args() method is available. If this this method is called,
|
||||
then parsing e.g.
|
||||
then parsing e.g.::
|
||||
|
||||
script --verbose cmd --debug /tmp/mything
|
||||
|
||||
will no longer return:
|
||||
will no longer return::
|
||||
|
||||
['cmd', '/tmp/mything']
|
||||
|
||||
as the leftover arguments, but will instead return:
|
||||
as the leftover arguments, but will instead return::
|
||||
|
||||
['cmd', '--debug', '/tmp/mything']
|
||||
|
||||
@ -307,9 +310,12 @@ class ConfigFileValueError(Error):
|
||||
def find_config_files(project=None, prog=None):
|
||||
"""Return a list of default configuration files.
|
||||
|
||||
:param project: an optional project name
|
||||
:param prog: the program name, defaulting to the basename of sys.argv[0]
|
||||
|
||||
We default to two config files: [${project}.conf, ${prog}.conf]
|
||||
|
||||
And we look for those config files in the following directories:
|
||||
And we look for those config files in the following directories::
|
||||
|
||||
~/.${project}/
|
||||
~/
|
||||
@ -324,9 +330,6 @@ def find_config_files(project=None, prog=None):
|
||||
'~/.foo/bar.conf']
|
||||
|
||||
If no project name is supplied, we only look for ${prog.conf}.
|
||||
|
||||
:param project: an optional project name
|
||||
:param prog: the program name, defaulting to the basename of sys.argv[0]
|
||||
"""
|
||||
if prog is None:
|
||||
prog = os.path.basename(sys.argv[0])
|
||||
|
@ -68,15 +68,15 @@ def enforce(context, action, target):
|
||||
:param context: nova context
|
||||
:param action: string representing the action to be checked
|
||||
this should be colon separated for clarity.
|
||||
i.e. compute:create_instance
|
||||
compute:attach_volume
|
||||
volume:attach_volume
|
||||
i.e. ``compute:create_instance``,
|
||||
``compute:attach_volume``,
|
||||
``volume:attach_volume``
|
||||
|
||||
:param object: dictionary representing the object of the action
|
||||
for object creation this should be a dictionary representing the
|
||||
location of the object e.g. {'project_id': context.project_id}
|
||||
location of the object e.g. ``{'project_id': context.project_id}``
|
||||
|
||||
:raises: `nova.exception.PolicyNotAllowed` if verification fails.
|
||||
:raises nova.exception.PolicyNotAllowed: if verification fails.
|
||||
|
||||
"""
|
||||
init()
|
||||
|
@ -184,6 +184,7 @@ class Scheduler(object):
|
||||
block_migration=False,
|
||||
disk_over_commit=False):
|
||||
"""Live migration scheduling method.
|
||||
|
||||
:param context:
|
||||
:param instance_id:
|
||||
:param dest: destination host
|
||||
|
@ -79,17 +79,20 @@ def compute_fill_first_cost_fn(host_state, weighing_properties):
|
||||
|
||||
def weighted_sum(weighted_fns, host_states, weighing_properties):
|
||||
"""Use the weighted-sum method to compute a score for an array of objects.
|
||||
|
||||
Normalize the results of the objective-functions so that the weights are
|
||||
meaningful regardless of objective-function's range.
|
||||
|
||||
host_list - [(host, HostInfo()), ...]
|
||||
weighted_fns - list of weights and functions like:
|
||||
[(weight, objective-functions), ...]
|
||||
weighing_properties is an arbitrary dict of values that can influence
|
||||
weights.
|
||||
:param host_list: ``[(host, HostInfo()), ...]``
|
||||
:param weighted_fns: list of weights and functions like::
|
||||
|
||||
Returns a single WeightedHost object which represents the best
|
||||
candidate.
|
||||
[(weight, objective-functions), ...]
|
||||
|
||||
:param weighing_properties: an arbitrary dict of values that can
|
||||
influence weights.
|
||||
|
||||
:returns: a single WeightedHost object which represents the best
|
||||
candidate.
|
||||
"""
|
||||
|
||||
# Make a grid of functions results.
|
||||
|
@ -137,11 +137,12 @@ class SchedulerManager(manager.Manager):
|
||||
:param context: security context
|
||||
:param host: hostname
|
||||
:returns:
|
||||
example format is below.
|
||||
{'resource':D, 'usage':{proj_id1:D, proj_id2:D}}
|
||||
D: {'vcpus': 3, 'memory_mb': 2048, 'local_gb': 2048,
|
||||
'vcpus_used': 12, 'memory_mb_used': 10240,
|
||||
'local_gb_used': 64}
|
||||
example format is below::
|
||||
|
||||
{'resource':D, 'usage':{proj_id1:D, proj_id2:D}}
|
||||
D: {'vcpus': 3, 'memory_mb': 2048, 'local_gb': 2048,
|
||||
'vcpus_used': 12, 'memory_mb_used': 10240,
|
||||
'local_gb_used': 64}
|
||||
|
||||
"""
|
||||
# Getting compute node info and related instances info
|
||||
|
@ -85,7 +85,7 @@ class TestFaults(test.TestCase):
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_raise(self):
|
||||
"""Ensure the ability to raise `Fault`s in WSGI-ified methods."""
|
||||
"""Ensure the ability to raise :class:`Fault` in WSGI-ified methods."""
|
||||
@webob.dec.wsgify
|
||||
def raiser(req):
|
||||
raise wsgi.Fault(webob.exc.HTTPNotFound(explanation='whut?'))
|
||||
|
@ -116,23 +116,25 @@ def vpn_ping(address, port, timeout=0.05, session_id=None):
|
||||
Returns False on a failure. Basic packet structure is below.
|
||||
|
||||
Client packet (14 bytes)::
|
||||
0 1 8 9 13
|
||||
+-+--------+-----+
|
||||
|x| cli_id |?????|
|
||||
+-+--------+-----+
|
||||
x = packet identifier 0x38
|
||||
cli_id = 64 bit identifier
|
||||
? = unknown, probably flags/padding
|
||||
|
||||
0 1 8 9 13
|
||||
+-+--------+-----+
|
||||
|x| cli_id |?????|
|
||||
+-+--------+-----+
|
||||
x = packet identifier 0x38
|
||||
cli_id = 64 bit identifier
|
||||
? = unknown, probably flags/padding
|
||||
|
||||
Server packet (26 bytes)::
|
||||
0 1 8 9 13 14 21 2225
|
||||
+-+--------+-----+--------+----+
|
||||
|x| srv_id |?????| cli_id |????|
|
||||
+-+--------+-----+--------+----+
|
||||
x = packet identifier 0x40
|
||||
cli_id = 64 bit identifier
|
||||
? = unknown, probably flags/padding
|
||||
bit 9 was 1 and the rest were 0 in testing
|
||||
|
||||
0 1 8 9 13 14 21 2225
|
||||
+-+--------+-----+--------+----+
|
||||
|x| srv_id |?????| cli_id |????|
|
||||
+-+--------+-----+--------+----+
|
||||
x = packet identifier 0x40
|
||||
cli_id = 64 bit identifier
|
||||
? = unknown, probably flags/padding
|
||||
bit 9 was 1 and the rest were 0 in testing
|
||||
|
||||
"""
|
||||
if session_id is None:
|
||||
@ -162,27 +164,29 @@ def fetchfile(url, target):
|
||||
|
||||
|
||||
def execute(*cmd, **kwargs):
|
||||
"""
|
||||
Helper method to execute command with optional retry.
|
||||
"""Helper method to execute command with optional retry.
|
||||
|
||||
If you add a run_as_root=True command, don't forget to add the
|
||||
corresponding filter to nova.rootwrap !
|
||||
|
||||
:cmd Passed to subprocess.Popen.
|
||||
:process_input Send to opened process.
|
||||
:check_exit_code Single bool, int, or list of allowed exit codes.
|
||||
Defaults to [0]. Raise exception.ProcessExecutionError
|
||||
unless program exits with one of these code.
|
||||
:delay_on_retry True | False. Defaults to True. If set to True, wait a
|
||||
short amount of time before retrying.
|
||||
:attempts How many times to retry cmd.
|
||||
:run_as_root True | False. Defaults to False. If set to True,
|
||||
the command is prefixed by the command specified
|
||||
in the root_helper FLAG.
|
||||
:param cmd: Passed to subprocess.Popen.
|
||||
:param process_input: Send to opened process.
|
||||
:param check_exit_code: Single bool, int, or list of allowed exit
|
||||
codes. Defaults to [0]. Raise
|
||||
exception.ProcessExecutionError unless
|
||||
program exits with one of these code.
|
||||
:param delay_on_retry: True | False. Defaults to True. If set to
|
||||
True, wait a short amount of time
|
||||
before retrying.
|
||||
:param attempts: How many times to retry cmd.
|
||||
:param run_as_root: True | False. Defaults to False. If set to True,
|
||||
the command is prefixed by the command specified
|
||||
in the root_helper FLAG.
|
||||
|
||||
:raises exception.Error on receiving unknown arguments
|
||||
:raises exception.ProcessExecutionError
|
||||
:raises exception.Error: on receiving unknown arguments
|
||||
:raises exception.ProcessExecutionError:
|
||||
|
||||
:returns a tuple, (stdout, stderr) from the spawned process, or None if
|
||||
:returns: a tuple, (stdout, stderr) from the spawned process, or None if
|
||||
the command fails.
|
||||
"""
|
||||
|
||||
@ -795,21 +799,23 @@ _semaphores = {}
|
||||
def synchronized(name, external=False):
|
||||
"""Synchronization decorator.
|
||||
|
||||
Decorating a method like so:
|
||||
@synchronized('mylock')
|
||||
def foo(self, *args):
|
||||
...
|
||||
Decorating a method like so::
|
||||
|
||||
@synchronized('mylock')
|
||||
def foo(self, *args):
|
||||
...
|
||||
|
||||
ensures that only one thread will execute the bar method at a time.
|
||||
|
||||
Different methods can share the same lock:
|
||||
@synchronized('mylock')
|
||||
def foo(self, *args):
|
||||
...
|
||||
Different methods can share the same lock::
|
||||
|
||||
@synchronized('mylock')
|
||||
def bar(self, *args):
|
||||
...
|
||||
@synchronized('mylock')
|
||||
def foo(self, *args):
|
||||
...
|
||||
|
||||
@synchronized('mylock')
|
||||
def bar(self, *args):
|
||||
...
|
||||
|
||||
This way only one of either foo or bar can be executing at a time.
|
||||
|
||||
@ -1601,7 +1607,8 @@ class UndoManager(object):
|
||||
def rollback_and_reraise(self, msg=None):
|
||||
"""Rollback a series of actions then re-raise the exception.
|
||||
|
||||
NOTE(sirp): This should only be called within an exception handler.
|
||||
.. note:: (sirp) This should only be called within an
|
||||
exception handler.
|
||||
"""
|
||||
with save_and_reraise_exception():
|
||||
if msg:
|
||||
|
@ -128,25 +128,29 @@ class ComputeDriver(object):
|
||||
Return the number of virtual machines that the hypervisor knows
|
||||
about.
|
||||
|
||||
:note This implementation works for all drivers, but it is
|
||||
not particularly efficient. Maintainers of the virt drivers are
|
||||
encouraged to override this method with something more
|
||||
efficient.
|
||||
.. note::
|
||||
|
||||
This implementation works for all drivers, but it is
|
||||
not particularly efficient. Maintainers of the virt drivers are
|
||||
encouraged to override this method with something more
|
||||
efficient.
|
||||
"""
|
||||
return len(self.list_instances())
|
||||
|
||||
def instance_exists(self, instance_id):
|
||||
"""Checks existence of an instance on the host.
|
||||
|
||||
:param instance_id: The ID / name of the instance to lookup
|
||||
|
||||
Returns True if an instance with the supplied ID exists on
|
||||
the host, False otherwise.
|
||||
|
||||
:note This implementation works for all drivers, but it is
|
||||
not particularly efficient. Maintainers of the virt drivers are
|
||||
encouraged to override this method with something more
|
||||
efficient.
|
||||
.. note::
|
||||
|
||||
:param instance_id: The ID / name of the instance to lookup
|
||||
This implementation works for all drivers, but it is
|
||||
not particularly efficient. Maintainers of the virt drivers are
|
||||
encouraged to override this method with something more
|
||||
efficient.
|
||||
"""
|
||||
return instance_id in self.list_instances()
|
||||
|
||||
@ -422,7 +426,7 @@ class ComputeDriver(object):
|
||||
host 'H0' and this method would still have been called. The point was
|
||||
that this method isn't called on the host where instances of that
|
||||
group are running (as is the case with
|
||||
:method:`refresh_security_group_rules`) but is called where references
|
||||
:py:meth:`refresh_security_group_rules`) but is called where references
|
||||
are made to authorizing those instances.
|
||||
|
||||
An error should be raised if the operation cannot complete.
|
||||
@ -436,7 +440,7 @@ class ComputeDriver(object):
|
||||
|
||||
When this is called, rules have either been added or removed from the
|
||||
datastore. You can retrieve rules with
|
||||
:method:`nova.db.provider_fw_rule_get_all`.
|
||||
:py:meth:`nova.db.provider_fw_rule_get_all`.
|
||||
|
||||
Provider rules take precedence over security group rules. If an IP
|
||||
would be allowed by a security group ingress rule, but blocked by
|
||||
@ -669,12 +673,12 @@ class ComputeDriver(object):
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_volume_connector(self, instance):
|
||||
"""
|
||||
Get connector information for the instance for attaching to volumes.
|
||||
"""Get connector information for the instance for attaching to volumes.
|
||||
|
||||
Connector information is a dictionary representing the ip of the
|
||||
machine that will be making the connection and and the name of the
|
||||
iscsi initiator as follows:
|
||||
iscsi initiator as follows::
|
||||
|
||||
{
|
||||
'ip': ip,
|
||||
'initiator': initiator,
|
||||
|
@ -88,7 +88,7 @@ class FirewallDriver(object):
|
||||
"""Create rules to block spoofing and allow dhcp.
|
||||
|
||||
This gets called when spawning an instance, before
|
||||
:method:`prepare_instance_filter`.
|
||||
:py:meth:`prepare_instance_filter`.
|
||||
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
@ -362,7 +362,7 @@ class IptablesFirewallDriver(FirewallDriver):
|
||||
self.add_filters_for_instance(instance)
|
||||
|
||||
def refresh_provider_fw_rules(self):
|
||||
"""See class:FirewallDriver: docs."""
|
||||
"""See :class:`FirewallDriver` docs."""
|
||||
self._do_refresh_provider_fw_rules()
|
||||
self.iptables.apply()
|
||||
|
||||
|
@ -2030,12 +2030,12 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
block_migration):
|
||||
"""Post operation of live migration at destination host.
|
||||
|
||||
:params ctxt: security context
|
||||
:params instance_ref:
|
||||
:param ctxt: security context
|
||||
:param instance_ref:
|
||||
nova.db.sqlalchemy.models.Instance object
|
||||
instance object that is migrated.
|
||||
:params network_info: instance network infomation
|
||||
:params : block_migration: if true, post operation of block_migraiton.
|
||||
:param network_info: instance network infomation
|
||||
:param block_migration: if true, post operation of block_migraiton.
|
||||
"""
|
||||
# Define migrated instance, otherwise, suspend/destroy does not work.
|
||||
dom_list = self._conn.listDefinedDomains()
|
||||
@ -2064,11 +2064,12 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
nova.db.sqlalchemy.models.Instance object
|
||||
instance object that is migrated.
|
||||
:return:
|
||||
json strings with below format.
|
||||
"[{'path':'disk', 'type':'raw',
|
||||
'virt_disk_size':'10737418240',
|
||||
'backing_file':'backing_file',
|
||||
'disk_size':'83886080'},...]"
|
||||
json strings with below format::
|
||||
|
||||
"[{'path':'disk', 'type':'raw',
|
||||
'virt_disk_size':'10737418240',
|
||||
'backing_file':'backing_file',
|
||||
'disk_size':'83886080'},...]"
|
||||
|
||||
"""
|
||||
disk_info = []
|
||||
|
@ -87,12 +87,13 @@ class VMWareVMOps(object):
|
||||
Creates a VM instance.
|
||||
|
||||
Steps followed are:
|
||||
|
||||
1. Create a VM with no disk and the specifics in the instance object
|
||||
like RAM size.
|
||||
like RAM size.
|
||||
2. Create a dummy vmdk of the size of the disk file that is to be
|
||||
uploaded. This is required just to create the metadata file.
|
||||
uploaded. This is required just to create the metadata file.
|
||||
3. Delete the -flat.vmdk file created in the above step and retain
|
||||
the metadata .vmdk file.
|
||||
the metadata .vmdk file.
|
||||
4. Upload the disk file.
|
||||
5. Attach the disk to the VM by reconfiguring the same.
|
||||
6. Power on the VM.
|
||||
@ -335,16 +336,17 @@ class VMWareVMOps(object):
|
||||
_power_on_vm()
|
||||
|
||||
def snapshot(self, context, instance, snapshot_name):
|
||||
"""
|
||||
Create snapshot from a running VM instance.
|
||||
"""Create snapshot from a running VM instance.
|
||||
|
||||
Steps followed are:
|
||||
|
||||
1. Get the name of the vmdk file which the VM points to right now.
|
||||
Can be a chain of snapshots, so we need to know the last in the
|
||||
chain.
|
||||
Can be a chain of snapshots, so we need to know the last in the
|
||||
chain.
|
||||
2. Create the snapshot. A new vmdk is created which the VM points to
|
||||
now. The earlier vmdk becomes read-only.
|
||||
now. The earlier vmdk becomes read-only.
|
||||
3. Call CopyVirtualDisk which coalesces the disk chain to form a single
|
||||
vmdk, rather a .vmdk metadata file and a -flat.vmdk disk data file.
|
||||
vmdk, rather a .vmdk metadata file and a -flat.vmdk disk data file.
|
||||
4. Now upload the -flat.vmdk file to the image store.
|
||||
5. Delete the coalesced .vmdk and -flat.vmdk created.
|
||||
"""
|
||||
|
@ -94,15 +94,15 @@ KERNEL_DIR = '/boot/guest'
|
||||
|
||||
|
||||
class ImageType:
|
||||
"""
|
||||
Enumeration class for distinguishing different image types
|
||||
0 - kernel image (goes on dom0's filesystem)
|
||||
1 - ramdisk image (goes on dom0's filesystem)
|
||||
2 - disk image (local SR, partitioned by objectstore plugin)
|
||||
3 - raw disk image (local SR, NOT partitioned by plugin)
|
||||
4 - vhd disk image (local SR, NOT inspected by XS, PV assumed for
|
||||
linux, HVM assumed for Windows)
|
||||
5 - ISO disk image (local SR, NOT partitioned by plugin)
|
||||
"""Enumeration class for distinguishing different image types
|
||||
|
||||
| 0 - kernel image (goes on dom0's filesystem)
|
||||
| 1 - ramdisk image (goes on dom0's filesystem)
|
||||
| 2 - disk image (local SR, partitioned by objectstore plugin)
|
||||
| 3 - raw disk image (local SR, NOT partitioned by plugin)
|
||||
| 4 - vhd disk image (local SR, NOT inspected by XS, PV assumed for
|
||||
| linux, HVM assumed for Windows)
|
||||
| 5 - ISO disk image (local SR, NOT partitioned by plugin)
|
||||
"""
|
||||
|
||||
KERNEL = 0
|
||||
|
@ -99,7 +99,7 @@ def make_step_decorator(context, instance):
|
||||
"""Factory to create a decorator that records instance progress as a series
|
||||
of discrete steps.
|
||||
|
||||
Each time the decorator is invoked we bump the total-step-count, so after:
|
||||
Each time the decorator is invoked we bump the total-step-count, so after::
|
||||
|
||||
@step
|
||||
def step1():
|
||||
@ -112,11 +112,12 @@ def make_step_decorator(context, instance):
|
||||
we have a total-step-count of 2.
|
||||
|
||||
Each time the step-function (not the step-decorator!) is invoked, we bump
|
||||
the current-step-count by 1, so after:
|
||||
the current-step-count by 1, so after::
|
||||
|
||||
step1()
|
||||
|
||||
the current-step-count would be 1 giving a progress of 1 / 2 * 100 or 50%.
|
||||
the current-step-count would be 1 giving a progress of ``1 / 2 *
|
||||
100`` or 50%.
|
||||
"""
|
||||
instance_uuid = instance['uuid']
|
||||
|
||||
@ -651,18 +652,18 @@ class VMOps(object):
|
||||
Steps involved in a XenServer snapshot:
|
||||
|
||||
1. XAPI-Snapshot: Snapshotting the instance using XenAPI. This
|
||||
creates: Snapshot (Template) VM, Snapshot VBD, Snapshot VDI,
|
||||
Snapshot VHD
|
||||
creates: Snapshot (Template) VM, Snapshot VBD, Snapshot VDI,
|
||||
Snapshot VHD
|
||||
|
||||
2. Wait-for-coalesce: The Snapshot VDI and Instance VDI both point to
|
||||
a 'base-copy' VDI. The base_copy is immutable and may be chained
|
||||
with other base_copies. If chained, the base_copies
|
||||
coalesce together, so, we must wait for this coalescing to occur to
|
||||
get a stable representation of the data on disk.
|
||||
a 'base-copy' VDI. The base_copy is immutable and may be chained
|
||||
with other base_copies. If chained, the base_copies
|
||||
coalesce together, so, we must wait for this coalescing to occur to
|
||||
get a stable representation of the data on disk.
|
||||
|
||||
3. Push-to-glance: Once coalesced, we call a plugin on the XenServer
|
||||
that will bundle the VHDs together and then push the bundle into
|
||||
Glance.
|
||||
that will bundle the VHDs together and then push the bundle into
|
||||
Glance.
|
||||
|
||||
"""
|
||||
template_vm_ref = None
|
||||
|
@ -238,13 +238,15 @@ class ISCSIDriver(VolumeDriver):
|
||||
|
||||
We make use of model provider properties as follows:
|
||||
|
||||
:provider_location: if present, contains the iSCSI target information
|
||||
in the same format as an ietadm discovery
|
||||
i.e. '<ip>:<port>,<portal> <target IQN>'
|
||||
``provider_location``
|
||||
if present, contains the iSCSI target information in the same
|
||||
format as an ietadm discovery
|
||||
i.e. '<ip>:<port>,<portal> <target IQN>'
|
||||
|
||||
:provider_auth: if present, contains a space-separated triple:
|
||||
'<auth method> <auth username> <auth password>'.
|
||||
`CHAP` is the only auth_method in use at the moment.
|
||||
``provider_auth``
|
||||
if present, contains a space-separated triple:
|
||||
'<auth method> <auth username> <auth password>'.
|
||||
`CHAP` is the only auth_method in use at the moment.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -424,7 +426,8 @@ class ISCSIDriver(VolumeDriver):
|
||||
|
||||
The iscsi driver returns a driver_volume_type of 'iscsi'.
|
||||
The format of the driver data is defined in _get_iscsi_properties.
|
||||
Example return value:
|
||||
Example return value::
|
||||
|
||||
{
|
||||
'driver_volume_type': 'iscsi'
|
||||
'data': {
|
||||
|
@ -266,7 +266,8 @@ class VolumeManager(manager.SchedulerDependentManager):
|
||||
This method calls the driver initialize_connection and returns
|
||||
it to the caller. The connector parameter is a dictionary with
|
||||
information about the host that will connect to the volume in the
|
||||
following format:
|
||||
following format::
|
||||
|
||||
{
|
||||
'ip': ip,
|
||||
'initiator': initiator,
|
||||
@ -279,7 +280,8 @@ class VolumeManager(manager.SchedulerDependentManager):
|
||||
connections.
|
||||
|
||||
driver is responsible for doing any necessary security setup and
|
||||
returning a connection_info dictionary in the following format:
|
||||
returning a connection_info dictionary in the following format::
|
||||
|
||||
{
|
||||
'driver_volume_type': driver_volume_type,
|
||||
'data': data,
|
||||
|
@ -19,8 +19,9 @@
|
||||
Handles all requests relating to Virtual Storage Arrays (VSAs).
|
||||
|
||||
Experimental code. Requires special VSA image.
|
||||
|
||||
For assistance and guidelines pls contact
|
||||
Zadara Storage Inc & Openstack community
|
||||
Zadara Storage Inc & Openstack community
|
||||
"""
|
||||
|
||||
from nova import compute
|
||||
@ -143,9 +144,8 @@ class API(base.Base):
|
||||
def create(self, context, display_name='', display_description='',
|
||||
vc_count=1, instance_type=None, image_name=None,
|
||||
availability_zone=None, storage=[], shared=None):
|
||||
"""
|
||||
Provision VSA instance with corresponding compute instances
|
||||
and associated volumes
|
||||
"""Provision VSA instance with compute instances and volumes
|
||||
|
||||
:param storage: List of dictionaries with following keys:
|
||||
disk_name, num_disks, size
|
||||
:param shared: Specifies if storage is dedicated or shared.
|
||||
|
Loading…
Reference in New Issue
Block a user