Indentaion fixes all over the place
This commit is contained in:
parent
b5af546ced
commit
d011fb5f44
@ -22,8 +22,7 @@ from reddwarf.common import wsgi
|
||||
from reddwarf.versions import VersionsController
|
||||
from reddwarf.flavor.service import FlavorController
|
||||
from reddwarf.instance.service import InstanceController
|
||||
from reddwarf.extensions.mgmt.host.instance.service import (
|
||||
HostInstanceController)
|
||||
from reddwarf.extensions.mgmt.host.instance import service as hostservice
|
||||
|
||||
|
||||
class API(wsgi.Router):
|
||||
@ -51,7 +50,8 @@ class API(wsgi.Router):
|
||||
mapper.resource("flavor", path, controller=flavor_resource)
|
||||
|
||||
def _host_instance_router(self, mapper):
|
||||
host_instance_resource = HostInstanceController().create_resource()
|
||||
host_controller = hostservice.HostInstanceController()
|
||||
host_instance_resource = host_controller.create_resource()
|
||||
path = "/{tenant_id}/mgmt/hosts/{host_id}/instances"
|
||||
mapper.resource("hostinstance", path,
|
||||
controller=host_instance_resource,
|
||||
|
@ -47,8 +47,7 @@ class AuthorizationMiddleware(wsgi.Middleware):
|
||||
def _factory(app):
|
||||
LOG.debug(_("Created auth middleware with config: %s") %
|
||||
local_config)
|
||||
return cls(app, [TenantBasedAuth()],
|
||||
**local_config)
|
||||
return cls(app, [TenantBasedAuth()], **local_config)
|
||||
return _factory
|
||||
|
||||
|
||||
@ -65,9 +64,8 @@ class TenantBasedAuth(object):
|
||||
LOG.debug(_("Authorized tenant '%(tenant_id)s' request: "
|
||||
"%(request)s") % locals())
|
||||
return True
|
||||
msg = _("User with tenant id %s cannot access this resource") \
|
||||
% tenant_id
|
||||
LOG.debug(msg)
|
||||
msg = _("User with tenant id %s cannot access this resource")
|
||||
LOG.debug(msg % tenant_id)
|
||||
raise webob.exc.HTTPForbidden(msg)
|
||||
|
||||
|
||||
|
@ -31,8 +31,8 @@ ResourceExtension = extensions.ResourceExtension
|
||||
class ReddwarfExtensionMiddleware(extensions.ExtensionMiddleware):
|
||||
|
||||
def __init__(self, application, config, ext_mgr=None):
|
||||
ext_mgr = ext_mgr or ExtensionManager(
|
||||
config['api_extensions_path'])
|
||||
ext_mgr = (ext_mgr or
|
||||
ExtensionManager(config['api_extensions_path']))
|
||||
mapper = routes.Mapper()
|
||||
|
||||
# extended resources
|
||||
|
@ -39,7 +39,8 @@ class PaginatedDataView(object):
|
||||
return []
|
||||
app_url = AppUrl(self.current_page_url)
|
||||
next_url = app_url.change_query_params(marker=self.next_page_marker)
|
||||
next_link = {'rel': 'next',
|
||||
next_link = {
|
||||
'rel': 'next',
|
||||
'href': str(next_url),
|
||||
}
|
||||
return [next_link]
|
||||
|
@ -36,8 +36,8 @@ def create_nova_client(context):
|
||||
COMPUTE_URL = CONFIG.get('nova_compute_url', 'http://localhost:8774/v2')
|
||||
PROXY_AUTH_URL = CONFIG.get('reddwarf_auth_url',
|
||||
'http://0.0.0.0:5000/v2.0')
|
||||
client = Client(context.user, context.auth_tok,
|
||||
project_id=context.tenant, auth_url=PROXY_AUTH_URL)
|
||||
client = Client(context.user, context.auth_tok, project_id=context.tenant,
|
||||
auth_url=PROXY_AUTH_URL)
|
||||
client.client.auth_token = context.auth_tok
|
||||
client.client.management_url = "%s/%s/" % (COMPUTE_URL, context.tenant)
|
||||
|
||||
|
@ -171,8 +171,8 @@ class Service(object):
|
||||
report_interval = config.Config.get('report_interval', 10)
|
||||
if not periodic_interval:
|
||||
periodic_interval = config.Config.get('periodic_interval', 60)
|
||||
service_obj = cls(host, binary, topic, manager,
|
||||
report_interval, periodic_interval)
|
||||
service_obj = cls(host, binary, topic, manager, report_interval,
|
||||
periodic_interval)
|
||||
|
||||
return service_obj
|
||||
|
||||
|
@ -49,7 +49,8 @@ LOG = logging.getLogger('reddwarf.common.wsgi')
|
||||
XMLNS = 'http://docs.openstack.org/database/api/v1.0'
|
||||
CUSTOM_PLURALS_METADATA = {'databases': '', 'users': ''}
|
||||
CUSTOM_SERIALIZER_METADATA = {
|
||||
'instance': {'status': '',
|
||||
'instance': {
|
||||
'status': '',
|
||||
'hostname': '',
|
||||
'id': '',
|
||||
'name': '',
|
||||
@ -64,7 +65,8 @@ CUSTOM_SERIALIZER_METADATA = {
|
||||
'deleted_at': '',
|
||||
'tenant_id': '',
|
||||
},
|
||||
'volume': {'size': '',
|
||||
'volume': {
|
||||
'size': '',
|
||||
'used': '',
|
||||
#mgmt/instance
|
||||
'id': '',
|
||||
@ -134,11 +136,12 @@ class Request(openstack_wsgi.Request):
|
||||
if format in ['json', 'xml']:
|
||||
return 'application/{0}'.format(parts[1])
|
||||
|
||||
ctypes = {'application/vnd.openstack.reddwarf+json':
|
||||
"application/json",
|
||||
ctypes = {
|
||||
'application/vnd.openstack.reddwarf+json': "application/json",
|
||||
'application/vnd.openstack.reddwarf+xml': "application/xml",
|
||||
'application/json': "application/json",
|
||||
'application/xml': "application/xml"}
|
||||
'application/xml': "application/xml",
|
||||
}
|
||||
bm = self.accept.best_match(ctypes.keys())
|
||||
|
||||
return ctypes.get(bm, 'application/json')
|
||||
@ -205,7 +208,8 @@ class Resource(openstack_wsgi.Resource):
|
||||
if getattr(self.controller, action, None) is None:
|
||||
return Fault(webob.exc.HTTPNotFound())
|
||||
try:
|
||||
result = super(Resource, self).execute_action(action,
|
||||
result = super(Resource, self).execute_action(
|
||||
action,
|
||||
request,
|
||||
**action_args)
|
||||
if type(result) is dict:
|
||||
@ -221,7 +225,8 @@ class Resource(openstack_wsgi.Resource):
|
||||
return Fault(http_error)
|
||||
except Exception as error:
|
||||
LOG.exception(error)
|
||||
return Fault(webob.exc.HTTPInternalServerError(str(error),
|
||||
return Fault(webob.exc.HTTPInternalServerError(
|
||||
str(error),
|
||||
request=request))
|
||||
|
||||
def _get_http_error(self, error):
|
||||
@ -285,8 +290,7 @@ class Controller(object):
|
||||
exception.ComputeInstanceNotFound,
|
||||
exception.ModelNotFoundError,
|
||||
],
|
||||
webob.exc.HTTPConflict: [
|
||||
],
|
||||
webob.exc.HTTPConflict: [],
|
||||
webob.exc.HTTPRequestEntityTooLarge: [
|
||||
exception.OverLimit,
|
||||
exception.QuotaExceeded,
|
||||
@ -307,7 +311,8 @@ class Controller(object):
|
||||
def create_resource(self):
|
||||
serializer = ReddwarfResponseSerializer(
|
||||
body_serializers={'application/xml': ReddwarfXMLDictSerializer()})
|
||||
return Resource(self,
|
||||
return Resource(
|
||||
self,
|
||||
ReddwarfRequestDeserializer(),
|
||||
serializer,
|
||||
self.exception_map)
|
||||
@ -328,7 +333,8 @@ class ReddwarfRequestDeserializer(RequestDeserializer):
|
||||
|
||||
def __init__(self, body_deserializers=None, headers_deserializer=None,
|
||||
supported_content_types=None):
|
||||
super(ReddwarfRequestDeserializer, self).__init__(body_deserializers,
|
||||
super(ReddwarfRequestDeserializer, self).__init__(
|
||||
body_deserializers,
|
||||
headers_deserializer,
|
||||
supported_content_types)
|
||||
|
||||
@ -392,7 +398,8 @@ class ReddwarfXMLDictSerializer(openstack_wsgi.XMLDictSerializer):
|
||||
metadata['attributes'] = CUSTOM_SERIALIZER_METADATA
|
||||
if hasattr(data, "to_xml"):
|
||||
return data.to_xml()
|
||||
return super(ReddwarfXMLDictSerializer, self)._to_xml_node(doc,
|
||||
return super(ReddwarfXMLDictSerializer, self)._to_xml_node(
|
||||
doc,
|
||||
metadata,
|
||||
nodename,
|
||||
data)
|
||||
@ -410,13 +417,15 @@ class ReddwarfResponseSerializer(openstack_wsgi.ResponseSerializer):
|
||||
"""
|
||||
if isinstance(data, Result):
|
||||
data = data.data(content_type)
|
||||
super(ReddwarfResponseSerializer, self).serialize_body(response,
|
||||
super(ReddwarfResponseSerializer, self).serialize_body(
|
||||
response,
|
||||
data,
|
||||
content_type,
|
||||
action)
|
||||
|
||||
def serialize_headers(self, response, data, action):
|
||||
super(ReddwarfResponseSerializer, self).serialize_headers(response,
|
||||
super(ReddwarfResponseSerializer, self).serialize_headers(
|
||||
response,
|
||||
data,
|
||||
action)
|
||||
if isinstance(data, Result):
|
||||
|
@ -21,7 +21,8 @@ from reddwarf.common import utils
|
||||
from reddwarf.common import config
|
||||
|
||||
|
||||
db_api = utils.import_object(config.Config.get("db_api_implementation",
|
||||
db_api = utils.import_object(
|
||||
config.Config.get("db_api_implementation",
|
||||
"reddwarf.db.sqlalchemy.api"))
|
||||
|
||||
|
||||
@ -55,7 +56,8 @@ class Query(object):
|
||||
db_api.delete_all(self._query_func, self._model, **self._conditions)
|
||||
|
||||
def limit(self, limit=200, marker=None, marker_column=None):
|
||||
return db_api.find_all_by_limit(self._query_func,
|
||||
return db_api.find_all_by_limit(
|
||||
self._query_func,
|
||||
self._model,
|
||||
self._conditions,
|
||||
limit=limit,
|
||||
@ -88,10 +90,12 @@ def add_options(parser):
|
||||
help_text = ("The following configuration options are specific to the "
|
||||
"Reddwarf database.")
|
||||
|
||||
group = optparse.OptionGroup(parser,
|
||||
group = optparse.OptionGroup(
|
||||
parser,
|
||||
"Registry Database Options",
|
||||
help_text)
|
||||
group.add_option('--sql-connection',
|
||||
group.add_option(
|
||||
'--sql-connection',
|
||||
metavar="CONNECTION",
|
||||
default=None,
|
||||
help="A valid SQLAlchemy connection string for the "
|
||||
|
@ -32,7 +32,9 @@ from reddwarf.db.sqlalchemy.migrate_repo.schema import Table
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
instances = Table('instances', meta,
|
||||
instances = Table(
|
||||
'instances',
|
||||
meta,
|
||||
Column('id', String(36), primary_key=True, nullable=False),
|
||||
Column('created', DateTime()),
|
||||
Column('updated', DateTime()),
|
||||
|
@ -32,7 +32,9 @@ from reddwarf.db.sqlalchemy.migrate_repo.schema import Table
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
service_images = Table('service_images', meta,
|
||||
service_images = Table(
|
||||
'service_images',
|
||||
meta,
|
||||
Column('id', String(36), primary_key=True, nullable=False),
|
||||
Column('service_name', String(255)),
|
||||
Column('image_id', String(255)))
|
||||
|
@ -32,7 +32,9 @@ from reddwarf.db.sqlalchemy.migrate_repo.schema import Table
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
service_statuses = Table('service_statuses', meta,
|
||||
service_statuses = Table(
|
||||
'service_statuses',
|
||||
meta,
|
||||
Column('id', String(36), primary_key=True, nullable=False),
|
||||
Column('instance_id', String(36), nullable=False),
|
||||
Column('status_id', Integer(), nullable=False),
|
||||
|
@ -29,7 +29,9 @@ from reddwarf.db.sqlalchemy.migrate_repo.schema import Table
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
root_enabled_history = Table('root_enabled_history', meta,
|
||||
root_enabled_history = Table(
|
||||
'root_enabled_history',
|
||||
meta,
|
||||
Column('id', String(36), primary_key=True, nullable=False),
|
||||
Column('user', String(length=255)),
|
||||
Column('created', DateTime()),
|
||||
|
@ -32,7 +32,9 @@ from reddwarf.db.sqlalchemy.migrate_repo.schema import Table
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
agent_heartbeats = Table('agent_heartbeats', meta,
|
||||
agent_heartbeats = Table(
|
||||
'agent_heartbeats',
|
||||
meta,
|
||||
Column('id', String(36), primary_key=True, nullable=False),
|
||||
Column('instance_id', String(36), nullable=False),
|
||||
Column('updated_at', DateTime()))
|
||||
|
@ -29,7 +29,8 @@ from reddwarf.db.sqlalchemy.migrate_repo.schema import String
|
||||
meta = MetaData()
|
||||
|
||||
|
||||
dns_records = Table('dns_records', meta,
|
||||
dns_records = Table(
|
||||
'dns_records', meta,
|
||||
Column('name', String(length=255), primary_key=True),
|
||||
Column('record_id', String(length=64)))
|
||||
|
||||
|
@ -31,7 +31,9 @@ from reddwarf.db.sqlalchemy.migrate_repo.schema import Table
|
||||
meta = MetaData()
|
||||
|
||||
|
||||
usage_events = Table('usage_events', meta,
|
||||
usage_events = Table(
|
||||
'usage_events',
|
||||
meta,
|
||||
Column('id', String(36), primary_key=True, nullable=False),
|
||||
Column('instance_name', String(36)),
|
||||
Column('tenant_id', String(36)),
|
||||
|
@ -127,7 +127,8 @@ def db_sync(options, version=None, repo_path=None):
|
||||
def get_migrate_repo_path(repo_path=None):
|
||||
"""Get the path for the migrate repository."""
|
||||
|
||||
default_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
||||
default_path = os.path.join(
|
||||
os.path.abspath(os.path.dirname(__file__)),
|
||||
'migrate_repo')
|
||||
repo_path = repo_path or default_path
|
||||
assert os.path.exists(repo_path)
|
||||
|
@ -90,9 +90,11 @@ class DnsEntry(object):
|
||||
self.ttl = ttl
|
||||
|
||||
def __repr__(self):
|
||||
return 'DnsEntry(name="%s", content="%s", type="%s", ' \
|
||||
'ttl=%s, priority=%s, dns_zone=%s)' % (self.name, self.content,
|
||||
self.type, self.ttl, self.priority, self.dns_zone)
|
||||
msg = ('DnsEntry(name="%s", content="%s", type="%s", '
|
||||
'ttl=%s, priority=%s, dns_zone=%s)')
|
||||
params = (self.name, self.content, self.type, self.ttl, self.priority,
|
||||
self.dns_zone)
|
||||
return msg % params
|
||||
|
||||
def __str__(self):
|
||||
return "{ name:%s, content:%s, type:%s, zone:%s }" % \
|
||||
|
@ -32,7 +32,8 @@ class DnsManager(object):
|
||||
def __init__(self, dns_driver=None, dns_instance_entry_factory=None,
|
||||
*args, **kwargs):
|
||||
if not dns_driver:
|
||||
dns_driver = config.Config.get("dns_driver",
|
||||
dns_driver = config.Config.get(
|
||||
"dns_driver",
|
||||
"reddwarf.dns.driver.DnsDriver")
|
||||
dns_driver = utils.import_object(dns_driver)
|
||||
self.driver = dns_driver()
|
||||
|
@ -65,13 +65,13 @@ class EntryToRecordConverter(object):
|
||||
|
||||
def record_to_entry(self, record, dns_zone):
|
||||
entry_name = record.name
|
||||
return DnsEntry(name=entry_name, content=record.data, type=record.type,
|
||||
ttl=record.ttl, dns_zone=dns_zone)
|
||||
return DnsEntry(name=entry_name, content=record.data,
|
||||
type=record.type, ttl=record.ttl, dns_zone=dns_zone)
|
||||
|
||||
|
||||
def create_client_with_flag_values():
|
||||
"""Creates a RS DNSaaS client using the Flag values."""
|
||||
if DNS_MANAGEMENT_BASE_URL == None:
|
||||
if DNS_MANAGEMENT_BASE_URL is None:
|
||||
raise RuntimeError("Missing flag value for dns_management_base_url.")
|
||||
return DNSaas(DNS_ACCOUNT_ID, DNS_USERNAME, DNS_PASSKEY,
|
||||
auth_url=DNS_AUTH_URL,
|
||||
@ -96,9 +96,10 @@ def find_default_zone(dns_client, raise_if_zone_missing=True):
|
||||
pass
|
||||
if not raise_if_zone_missing:
|
||||
return RsDnsZone(id=None, name=domain_name)
|
||||
raise RuntimeError("The dns_domain_name from the FLAG values (%s) "
|
||||
"does not exist! account_id=%s, username=%s, LIST=%s"
|
||||
% (domain_name, DNS_ACCOUNT_ID, DNS_USERNAME, domains))
|
||||
msg = ("The dns_domain_name from the FLAG values (%s) "
|
||||
"does not exist! account_id=%s, username=%s, LIST=%s")
|
||||
params = (domain_name, DNS_ACCOUNT_ID, DNS_USERNAME, domains)
|
||||
raise RuntimeError(msg % params)
|
||||
|
||||
|
||||
class RsDnsDriver(object):
|
||||
@ -111,17 +112,18 @@ class RsDnsDriver(object):
|
||||
name=DNS_DOMAIN_NAME)
|
||||
self.converter = EntryToRecordConverter(self.default_dns_zone)
|
||||
if DNS_TTL < 300:
|
||||
raise Exception("TTL value '--dns_ttl=%s' should be greater than"\
|
||||
" 300" % DNS_TTL)
|
||||
msg = "TTL value '--dns_ttl=%s' should be greater than 300"
|
||||
raise Exception(msg % DNS_TTL)
|
||||
|
||||
def create_entry(self, entry):
|
||||
dns_zone = entry.dns_zone or self.default_dns_zone
|
||||
if dns_zone.id == None:
|
||||
if dns_zone.id is None:
|
||||
raise TypeError("The entry's dns_zone must have an ID specified.")
|
||||
name = entry.name # + "." + dns_zone.name
|
||||
LOG.debug("Going to create RSDNS entry %s." % name)
|
||||
try:
|
||||
future = self.dns_client.records.create(domain=dns_zone.id,
|
||||
future = self.dns_client.records.create(
|
||||
domain=dns_zone.id,
|
||||
record_name=name,
|
||||
record_data=entry.content,
|
||||
record_type=entry.type,
|
||||
@ -151,7 +153,8 @@ class RsDnsDriver(object):
|
||||
dns_zone = dns_zone or self.default_dns_zone
|
||||
long_name = name
|
||||
db_record = DnsRecord.find_by(name=name)
|
||||
record = self.dns_client.records.get(domain_id=dns_zone.id,
|
||||
record = self.dns_client.records.get(
|
||||
domain_id=dns_zone.id,
|
||||
record_id=db_record.record_id)
|
||||
if record.name != name or record.type != 'A':
|
||||
LOG.error("Tried to delete DNS record with name=%s, id=%s, but the"
|
||||
@ -159,14 +162,16 @@ class RsDnsDriver(object):
|
||||
"type %s." % (name, db_record.id, record.name,
|
||||
record.type))
|
||||
raise exception.DnsRecordNotFound(name)
|
||||
self.dns_client.records.delete(domain_id=dns_zone.id,
|
||||
self.dns_client.records.delete(
|
||||
domain_id=dns_zone.id,
|
||||
record_id=record.id)
|
||||
db_record.delete()
|
||||
|
||||
def get_entries(self, name=None, content=None, dns_zone=None):
|
||||
dns_zone = dns_zone or self.defaucreate_entrylt_dns_zone
|
||||
long_name = name # self.converter.name_to_long_name(name)
|
||||
records = self.dns_client.records.list(domain_id=dns_zone.id,
|
||||
records = self.dns_client.records.list(
|
||||
domain_id=dns_zone.id,
|
||||
record_name=long_name,
|
||||
record_address=content)
|
||||
return [self.converter.record_to_entry(record, dns_zone)
|
||||
@ -202,8 +207,8 @@ class RsDnsInstanceEntryFactory(object):
|
||||
id = instance_id
|
||||
hostname = ("%s.%s" % (hashlib.sha1(id).hexdigest(),
|
||||
self.default_dns_zone.name))
|
||||
return DnsEntry(name=hostname, content=None, type="A",
|
||||
ttl=DNS_TTL, dns_zone=self.default_dns_zone)
|
||||
return DnsEntry(name=hostname, content=None, type="A", ttl=DNS_TTL,
|
||||
dns_zone=self.default_dns_zone)
|
||||
|
||||
|
||||
class RsDnsZone(object):
|
||||
@ -213,8 +218,9 @@ class RsDnsZone(object):
|
||||
self.id = id
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, RsDnsZone) and\
|
||||
self.name == other.name and self.id == other.id
|
||||
return (isinstance(other, RsDnsZone) and
|
||||
self.name == other.name and
|
||||
self.id == other.id)
|
||||
|
||||
def __str__(self):
|
||||
return "%s:%s" % (self.id, self.name)
|
||||
|
@ -45,7 +45,8 @@ class Account(extensions.ExtensionsDescriptor):
|
||||
serializer = wsgi.ReddwarfResponseSerializer(
|
||||
body_serializers={'application/xml':
|
||||
wsgi.ReddwarfXMLDictSerializer()})
|
||||
resource = extensions.ResourceExtension('{tenant_id}/mgmt/accounts',
|
||||
resource = extensions.ResourceExtension(
|
||||
'{tenant_id}/mgmt/accounts',
|
||||
service.AccountController(),
|
||||
deserializer=wsgi.RequestDeserializer(),
|
||||
serializer=serializer)
|
||||
|
@ -37,8 +37,8 @@ class AccountController(wsgi.Controller):
|
||||
def show(self, req, tenant_id, id):
|
||||
"""Return a account and instances associated with a single account."""
|
||||
LOG.info(_("req : '%s'\n\n") % req)
|
||||
LOG.info(_("Showing account information for '%s' to '%s'")
|
||||
% (id, tenant_id))
|
||||
LOG.info(_("Showing account information for '%s' to '%s'") %
|
||||
(id, tenant_id))
|
||||
|
||||
context = req.environ[wsgi.CONTEXT_KEY]
|
||||
account = models.Account.load(context, id)
|
||||
|
@ -31,7 +31,8 @@ class AccountView(object):
|
||||
def data(self):
|
||||
instance_list = [InstanceView(instance).data()
|
||||
for instance in self.account.instances]
|
||||
return {'account': {
|
||||
return {
|
||||
'account': {
|
||||
'id': self.account.id,
|
||||
'instances': instance_list,
|
||||
}
|
||||
|
@ -21,8 +21,7 @@ from reddwarf.common import extensions
|
||||
from reddwarf.common import wsgi
|
||||
from reddwarf.extensions.mgmt.instances.service import MgmtInstanceController
|
||||
from reddwarf.extensions.mgmt.host.service import HostController
|
||||
from reddwarf.extensions.mgmt.host.instance.service import (
|
||||
HostInstanceController)
|
||||
from reddwarf.extensions.mgmt.host.instance import service as hostservice
|
||||
from reddwarf.extensions.mgmt.volume.service import StorageController
|
||||
|
||||
|
||||
@ -51,40 +50,41 @@ class Mgmt(extensions.ExtensionsDescriptor):
|
||||
serializer = wsgi.ReddwarfResponseSerializer(
|
||||
body_serializers={'application/xml':
|
||||
wsgi.ReddwarfXMLDictSerializer()})
|
||||
instances = extensions.ResourceExtension('{tenant_id}/mgmt/instances',
|
||||
instances = extensions.ResourceExtension(
|
||||
'{tenant_id}/mgmt/instances',
|
||||
MgmtInstanceController(),
|
||||
deserializer=wsgi.ReddwarfRequestDeserializer(),
|
||||
serializer=serializer,
|
||||
member_actions={'root': 'GET',
|
||||
'diagnostics': 'GET',
|
||||
'hwinfo': 'GET',
|
||||
'action': 'POST'},
|
||||
)
|
||||
'action': 'POST'})
|
||||
resources.append(instances)
|
||||
hosts = extensions.ResourceExtension('{tenant_id}/mgmt/hosts',
|
||||
|
||||
hosts = extensions.ResourceExtension(
|
||||
'{tenant_id}/mgmt/hosts',
|
||||
HostController(),
|
||||
deserializer=wsgi.RequestDeserializer(),
|
||||
serializer=serializer,
|
||||
member_actions={},
|
||||
)
|
||||
member_actions={})
|
||||
resources.append(hosts)
|
||||
|
||||
storage = extensions.ResourceExtension('{tenant_id}/mgmt/storage',
|
||||
storage = extensions.ResourceExtension(
|
||||
'{tenant_id}/mgmt/storage',
|
||||
StorageController(),
|
||||
deserializer=wsgi.RequestDeserializer(),
|
||||
serializer=serializer,
|
||||
member_actions={},
|
||||
)
|
||||
member_actions={})
|
||||
resources.append(storage)
|
||||
|
||||
host_instances = extensions.ResourceExtension('instances',
|
||||
HostInstanceController(),
|
||||
host_instances = extensions.ResourceExtension(
|
||||
'instances',
|
||||
hostservice.HostInstanceController(),
|
||||
parent={'member_name': 'host',
|
||||
'collection_name': '{tenant_id}/mgmt/hosts'},
|
||||
deserializer=wsgi.RequestDeserializer(),
|
||||
serializer=serializer,
|
||||
collection_actions={'action': 'POST'},
|
||||
)
|
||||
collection_actions={'action': 'POST'})
|
||||
resources.append(host_instances)
|
||||
|
||||
return resources
|
||||
|
@ -35,9 +35,7 @@ class HostInstanceController(wsgi.Controller):
|
||||
raise exception.BadRequest(_("Invalid request body."))
|
||||
context = req.environ[wsgi.CONTEXT_KEY]
|
||||
host = models.DetailedHost.load(context, host_id)
|
||||
_actions = {
|
||||
'update': self._action_update
|
||||
}
|
||||
_actions = {'update': self._action_update}
|
||||
selected_action = None
|
||||
for key in body:
|
||||
if key in _actions:
|
||||
|
@ -35,8 +35,10 @@ def load_mgmt_instances(context, deleted=None):
|
||||
db_infos = instance_models.DBInstance.find_all(deleted=deleted)
|
||||
else:
|
||||
db_infos = instance_models.DBInstance.find_all()
|
||||
instances = MgmtInstances.load_status_from_existing(context,
|
||||
db_infos, mgmt_servers)
|
||||
instances = MgmtInstances.load_status_from_existing(
|
||||
context,
|
||||
db_infos,
|
||||
mgmt_servers)
|
||||
return instances
|
||||
|
||||
|
||||
|
@ -73,10 +73,14 @@ class MgmtInstanceController(InstanceController):
|
||||
server = models.DetailedMgmtInstance.load(context, id)
|
||||
root_history = mysql_models.RootHistory.load(context=context,
|
||||
instance_id=id)
|
||||
return wsgi.Result(views.MgmtInstanceDetailView(server, req=req,
|
||||
return wsgi.Result(
|
||||
views.MgmtInstanceDetailView(
|
||||
server,
|
||||
req=req,
|
||||
add_addresses=self.add_addresses,
|
||||
add_volumes=self.add_volumes,
|
||||
root_history=root_history).data(), 200)
|
||||
root_history=root_history).data(),
|
||||
200)
|
||||
|
||||
@admin_context
|
||||
def action(self, req, body, tenant_id, id):
|
||||
|
@ -126,7 +126,8 @@ class RootHistoryView(object):
|
||||
self.user = user_id
|
||||
|
||||
def data(self):
|
||||
return {'root_history': {
|
||||
return {
|
||||
'root_history': {
|
||||
'id': self.instance_id,
|
||||
'enabled': self.enabled,
|
||||
'user': self.user,
|
||||
@ -141,7 +142,8 @@ class HwInfoView(object):
|
||||
self.hwinfo = hwinfo
|
||||
|
||||
def data(self):
|
||||
return {'hwinfo': {
|
||||
return {
|
||||
'hwinfo': {
|
||||
'mem_total': self.hwinfo['mem_total'],
|
||||
'num_cpus': self.hwinfo['num_cpus'],
|
||||
}
|
||||
@ -155,7 +157,8 @@ class DiagnosticsView(object):
|
||||
self.diagnostics = diagnostics
|
||||
|
||||
def data(self):
|
||||
return {'diagnostics': {
|
||||
return {
|
||||
'diagnostics': {
|
||||
'version': self.diagnostics['version'],
|
||||
'threads': self.diagnostics['threads'],
|
||||
'fdSize': self.diagnostics['fd_size'],
|
||||
|
@ -29,8 +29,7 @@ class StorageView(object):
|
||||
'provision': {'total': self.storage.prov_total,
|
||||
'available': self.storage.prov_avail,
|
||||
'percent': self.storage.prov_percent},
|
||||
'used': self.storage.used
|
||||
}
|
||||
'used': self.storage.used}
|
||||
|
||||
|
||||
class StoragesView(object):
|
||||
|
@ -35,9 +35,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def persisted_models():
|
||||
return {
|
||||
'root_enabled_history': RootHistory,
|
||||
}
|
||||
return {'root_enabled_history': RootHistory}
|
||||
|
||||
|
||||
def load_and_verify(context, instance_id):
|
||||
@ -66,10 +64,13 @@ class User(object):
|
||||
client = create_guest_client(context, instance_id)
|
||||
for user in users:
|
||||
user_name = user['_name']
|
||||
existing_users, _nadda = Users.load_with_client(client, limit=1,
|
||||
marker=user_name, include_marker=True)
|
||||
if len(existing_users) > 0 and \
|
||||
str(existing_users[0].name) == str(user_name):
|
||||
existing_users, _nadda = Users.load_with_client(
|
||||
client,
|
||||
limit=1,
|
||||
marker=user_name,
|
||||
include_marker=True)
|
||||
if (len(existing_users) > 0 and
|
||||
str(existing_users[0].name) == str(user_name)):
|
||||
raise exception.UserAlreadyExists(name=user_name)
|
||||
return client.create_user(users)
|
||||
|
||||
@ -158,8 +159,10 @@ class Users(object):
|
||||
|
||||
@classmethod
|
||||
def load_with_client(cls, client, limit, marker, include_marker):
|
||||
user_list, next_marker = client.list_users(limit=limit,
|
||||
marker=marker, include_marker=include_marker)
|
||||
user_list, next_marker = client.list_users(
|
||||
limit=limit,
|
||||
marker=marker,
|
||||
include_marker=include_marker)
|
||||
model_users = []
|
||||
ignore_users = CONFIG.get_list('ignore_users', [])
|
||||
for user in user_list:
|
||||
@ -193,10 +196,13 @@ class Schema(object):
|
||||
client = create_guest_client(context, instance_id)
|
||||
for schema in schemas:
|
||||
schema_name = schema['_name']
|
||||
existing_schema, _nadda = Schemas.load_with_client(client, limit=1,
|
||||
marker=schema_name, include_marker=True)
|
||||
if len(existing_schema) > 0 and \
|
||||
str(existing_schema[0].name) == str(schema_name):
|
||||
existing_schema, _nadda = Schemas.load_with_client(
|
||||
client,
|
||||
limit=1,
|
||||
marker=schema_name,
|
||||
include_marker=True)
|
||||
if (len(existing_schema) > 0 and
|
||||
str(existing_schema[0].name) == str(schema_name)):
|
||||
raise exception.DatabaseAlreadyExists(name=schema_name)
|
||||
return client.create_database(schemas)
|
||||
|
||||
@ -216,8 +222,10 @@ class Schemas(object):
|
||||
|
||||
@classmethod
|
||||
def load_with_client(cls, client, limit, marker, include_marker):
|
||||
schemas, next_marker = client.list_databases(limit=limit,
|
||||
marker=marker, include_marker=include_marker)
|
||||
schemas, next_marker = client.list_databases(
|
||||
limit=limit,
|
||||
marker=marker,
|
||||
include_marker=include_marker)
|
||||
model_schemas = []
|
||||
ignore_dbs = CONFIG.get_list('ignore_dbs', [])
|
||||
for schema in schemas:
|
||||
|
@ -26,12 +26,14 @@ class FlavorView(object):
|
||||
self.req = req
|
||||
|
||||
def data(self):
|
||||
return {"flavor": {
|
||||
return {
|
||||
"flavor": {
|
||||
'id': int(self.flavor.id),
|
||||
'links': self._build_links(),
|
||||
'name': self.flavor.name,
|
||||
'ram': self.flavor.ram,
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
def _build_links(self):
|
||||
return create_links("flavors", self.req, self.flavor.id)
|
||||
|
@ -152,7 +152,8 @@ class API(object):
|
||||
"""Make an asynchronous call to prepare the guest
|
||||
as a database container"""
|
||||
LOG.debug(_("Sending the call to prepare the Guest"))
|
||||
self._cast_with_consumer("prepare", databases=databases,
|
||||
self._cast_with_consumer(
|
||||
"prepare", databases=databases,
|
||||
memory_mb=memory_mb, users=users, device_path=device_path,
|
||||
mount_point=mount_point)
|
||||
|
||||
|
@ -286,12 +286,11 @@ class MySQLDatabase(Base):
|
||||
if any([not value,
|
||||
not self._is_valid(value),
|
||||
not self.dbname.match(value),
|
||||
string.find("%r" % value, "\\") != -1,
|
||||
]):
|
||||
string.find("%r" % value, "\\") != -1]):
|
||||
raise ValueError("'%s' is not a valid database name" % value)
|
||||
elif len(value) > 64:
|
||||
raise ValueError("Database name '%s' is too long. Max length = 64"
|
||||
% value)
|
||||
msg = "Database name '%s' is too long. Max length = 64"
|
||||
raise ValueError(msg % value)
|
||||
else:
|
||||
self._name = value
|
||||
|
||||
@ -312,8 +311,8 @@ class MySQLDatabase(Base):
|
||||
pass
|
||||
elif self._character_set:
|
||||
if not value in self.charset[self._character_set]:
|
||||
raise ValueError("'%s' not a valid collation for charset '%s'"
|
||||
% (value, self._character_set))
|
||||
msg = "'%s' not a valid collation for charset '%s'"
|
||||
raise ValueError(msg % (value, self._character_set))
|
||||
self._collate = value
|
||||
else:
|
||||
if not value in self.collation:
|
||||
@ -352,9 +351,9 @@ class MySQLUser(Base):
|
||||
self._databases = []
|
||||
|
||||
def _is_valid(self, value):
|
||||
if (not value or
|
||||
self.not_supported_chars.search(value) or
|
||||
string.find("%r" % value, "\\") != -1):
|
||||
if any([not value,
|
||||
self.not_supported_chars.search(value),
|
||||
string.find("%r" % value, "\\") != -1]):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@ -374,8 +373,8 @@ class MySQLUser(Base):
|
||||
if not self._is_valid_user_name(value):
|
||||
raise ValueError("'%s' is not a valid user name" % value)
|
||||
elif len(value) > 16:
|
||||
raise ValueError("User name '%s' is too long. Max length = 16"
|
||||
% value)
|
||||
raise ValueError("User name '%s' is too long. Max length = 16" %
|
||||
value)
|
||||
else:
|
||||
self._name = value
|
||||
|
||||
|
@ -78,8 +78,11 @@ def generate_random_password():
|
||||
|
||||
|
||||
def get_auth_password():
|
||||
pwd, err = utils.execute_with_timeout("sudo", "awk",
|
||||
"/password\\t=/{print $3}", "/etc/mysql/my.cnf")
|
||||
pwd, err = utils.execute_with_timeout(
|
||||
"sudo",
|
||||
"awk",
|
||||
"/password\\t=/{print $3}",
|
||||
"/etc/mysql/my.cnf")
|
||||
if err:
|
||||
LOG.err(err)
|
||||
raise RuntimeError("Problem reading my.cnf! : %s" % err)
|
||||
@ -176,7 +179,8 @@ class MySqlAppStatus(object):
|
||||
def _get_actual_db_status(self):
|
||||
global MYSQLD_ARGS
|
||||
try:
|
||||
out, err = utils.execute_with_timeout("/usr/bin/mysqladmin",
|
||||
out, err = utils.execute_with_timeout(
|
||||
"/usr/bin/mysqladmin",
|
||||
"ping", run_as_root=True)
|
||||
LOG.info("Service Status is RUNNING.")
|
||||
return rd_models.ServiceStatuses.RUNNING
|
||||
@ -208,9 +212,9 @@ class MySqlAppStatus(object):
|
||||
True if MySQL app should be installed and attempts to ascertain
|
||||
its status won't result in nonsense.
|
||||
"""
|
||||
return self.status is not None and \
|
||||
self.status != rd_models.ServiceStatuses.BUILDING and \
|
||||
self.status != rd_models.ServiceStatuses.FAILED
|
||||
return all([self.status is not None,
|
||||
self.status != rd_models.ServiceStatuses.BUILDING,
|
||||
self.status != rd_models.ServiceStatuses.FAILED])
|
||||
|
||||
@property
|
||||
def _is_mysql_restarting(self):
|
||||
@ -219,8 +223,8 @@ class MySqlAppStatus(object):
|
||||
@property
|
||||
def is_mysql_running(self):
|
||||
"""True if MySQL is running."""
|
||||
return self.status is not None and \
|
||||
self.status == rd_models.ServiceStatuses.RUNNING
|
||||
return (self.status is not None,
|
||||
self.status == rd_models.ServiceStatuses.RUNNING)
|
||||
|
||||
@staticmethod
|
||||
def _load_status():
|
||||
@ -338,8 +342,8 @@ class MySqlAdmin(object):
|
||||
mydb = models.MySQLDatabase()
|
||||
mydb.deserialize(database)
|
||||
t = text("""
|
||||
GRANT ALL PRIVILEGES ON `%s`.* TO `%s`@:host;"""
|
||||
% (mydb.name, user.name))
|
||||
GRANT ALL PRIVILEGES ON `%s`.* TO `%s`@:host;
|
||||
""" % (mydb.name, user.name))
|
||||
client.execute(t, host=host)
|
||||
|
||||
def delete_database(self, database):
|
||||
@ -420,8 +424,9 @@ class MySqlAdmin(object):
|
||||
if limit:
|
||||
q.limit = limit + 1
|
||||
if marker:
|
||||
q.where.append("schema_name %s '%s'"
|
||||
% (INCLUDE_MARKER_OPERATORS[include_marker], marker))
|
||||
q.where.append("schema_name %s '%s'" %
|
||||
(INCLUDE_MARKER_OPERATORS[include_marker],
|
||||
marker))
|
||||
t = text(str(q))
|
||||
database_names = client.execute(t)
|
||||
next_marker = None
|
||||
@ -454,8 +459,9 @@ class MySqlAdmin(object):
|
||||
q.where = ["host != 'localhost'"]
|
||||
q.order = ['User']
|
||||
if marker:
|
||||
q.where.append("User %s '%s'"
|
||||
% (INCLUDE_MARKER_OPERATORS[include_marker], marker))
|
||||
q.where.append("User %s '%s'" %
|
||||
(INCLUDE_MARKER_OPERATORS[include_marker],
|
||||
marker))
|
||||
if limit:
|
||||
q.limit = limit + 1
|
||||
t = text(str(q))
|
||||
@ -478,8 +484,8 @@ class MySqlAdmin(object):
|
||||
db_result = client.execute(t)
|
||||
for db in db_result:
|
||||
matches = re.match("^'(.+)'@", db['grantee'])
|
||||
if matches is not None and \
|
||||
matches.group(1) == mysql_user.name:
|
||||
if (matches is not None and
|
||||
matches.group(1) == mysql_user.name):
|
||||
mysql_db = models.MySQLDatabase()
|
||||
mysql_db.name = db['table_schema']
|
||||
mysql_user.databases.append(mysql_db.serialize())
|
||||
@ -703,7 +709,8 @@ class MySqlApp(object):
|
||||
|
||||
def _replace_mycnf_with_template(self, template_path, original_path):
|
||||
if os.path.isfile(template_path):
|
||||
utils.execute_with_timeout("sudo", "mv", original_path,
|
||||
utils.execute_with_timeout(
|
||||
"sudo", "mv", original_path,
|
||||
"%(name)s.%(date)s" % {'name': original_path,
|
||||
'date': date.today().isoformat()})
|
||||
utils.execute_with_timeout("sudo", "cp", template_path,
|
||||
|
@ -29,9 +29,7 @@ AGENT_HEARTBEAT = int(config.Config.get('agent_heartbeat_time', '10'))
|
||||
|
||||
|
||||
def persisted_models():
|
||||
return {
|
||||
'agent_heartbeats': AgentHeartBeat,
|
||||
}
|
||||
return {'agent_heartbeats': AgentHeartBeat}
|
||||
|
||||
|
||||
class AgentHeartBeat(dbmodels.DatabaseModelBase):
|
||||
@ -61,5 +59,5 @@ class AgentHeartBeat(dbmodels.DatabaseModelBase):
|
||||
|
||||
@staticmethod
|
||||
def is_active(agent):
|
||||
return (datetime.now() - agent.updated_at) < \
|
||||
timedelta(seconds=AGENT_HEARTBEAT)
|
||||
return (datetime.now() - agent.updated_at <
|
||||
timedelta(seconds=AGENT_HEARTBEAT))
|
||||
|
@ -91,8 +91,8 @@ class PkgAgent(object):
|
||||
i = child.expect(['.*password*',
|
||||
'E: Unable to locate package %s' % package_name,
|
||||
"Couldn't find package % s" % package_name,
|
||||
"dpkg was interrupted, you must manually run "
|
||||
"'sudo dpkg --configure -a'",
|
||||
("dpkg was interrupted, you must manually run "
|
||||
"'sudo dpkg --configure -a'"),
|
||||
"Unable to lock the administration directory",
|
||||
"Setting up %s*" % package_name,
|
||||
"is already the newest version"],
|
||||
@ -131,10 +131,10 @@ class PkgAgent(object):
|
||||
i = child.expect(['.*password*',
|
||||
'E: Unable to locate package %s' % package_name,
|
||||
'Package is in a very bad inconsistent state',
|
||||
"Sub-process /usr/bin/dpkg returned an "
|
||||
"error code",
|
||||
"dpkg was interrupted, you must manually run "
|
||||
"'sudo dpkg --configure -a'",
|
||||
("Sub-process /usr/bin/dpkg returned an error "
|
||||
"code"),
|
||||
("dpkg was interrupted, you must manually run "
|
||||
"'sudo dpkg --configure -a'"),
|
||||
"Unable to lock the administration directory",
|
||||
#'The following packages will be REMOVED',
|
||||
"Removing %s*" % package_name],
|
||||
|
@ -107,8 +107,8 @@ class VolumeDevice(object):
|
||||
utils.execute("sudo", "resize2fs", self.device_path)
|
||||
except ProcessExecutionError as err:
|
||||
LOG.error(err)
|
||||
raise GuestError("Error resizing the filesystem: %s"
|
||||
% self.device_path)
|
||||
raise GuestError("Error resizing the filesystem: %s" %
|
||||
self.device_path)
|
||||
|
||||
def _tmp_mount(self, mount_point):
|
||||
"""Mounts, but doesn't save to fstab."""
|
||||
@ -137,14 +137,16 @@ class VolumeMountPoint(object):
|
||||
"volume_type:%s, mount options:%s" %
|
||||
(self.device_path, self.mount_point, self.volume_fstype,
|
||||
self.mount_options))
|
||||
cmd = "sudo mount -t %s -o %s %s %s" % (self.volume_fstype,
|
||||
self.mount_options, self.device_path, self.mount_point)
|
||||
cmd = ("sudo mount -t %s -o %s %s %s" %
|
||||
(self.volume_fstype, self.mount_options, self.device_path,
|
||||
self.mount_point))
|
||||
child = pexpect.spawn(cmd)
|
||||
child.expect(pexpect.EOF)
|
||||
|
||||
def write_to_fstab(self):
|
||||
fstab_line = "%s\t%s\t%s\t%s\t0\t0" % (self.device_path,
|
||||
self.mount_point, self.volume_fstype, self.mount_options)
|
||||
fstab_line = ("%s\t%s\t%s\t%s\t0\t0" %
|
||||
(self.device_path, self.mount_point, self.volume_fstype,
|
||||
self.mount_options))
|
||||
LOG.debug("Writing new line to fstab:%s" % fstab_line)
|
||||
utils.execute("sudo", "cp", "/etc/fstab", "/etc/fstab.orig")
|
||||
utils.execute("sudo", "cp", "/etc/fstab", "/tmp/newfstab")
|
||||
|
@ -180,8 +180,9 @@ class SimpleInstance(object):
|
||||
if self.db_info.server_status in ["ACTIVE", "SHUTDOWN"]:
|
||||
return InstanceStatus.SHUTDOWN
|
||||
else:
|
||||
LOG.error(_("While shutting down instance (%s): server had "
|
||||
" status (%s).") % (self.id, self.db_info.server_status))
|
||||
msg = _("While shutting down instance (%s): server had "
|
||||
"status (%s).")
|
||||
LOG.error(msg % (self.id, self.db_info.server_status))
|
||||
return InstanceStatus.ERROR
|
||||
|
||||
### Check against the service status.
|
||||
@ -293,8 +294,8 @@ def load_instance_with_guest(cls, context, id):
|
||||
LOG.warn(mnfe)
|
||||
return instance
|
||||
|
||||
if instance.status not in AGENT_INVALID_STATUSES and \
|
||||
agent_models.AgentHeartBeat.is_active(agent):
|
||||
if (instance.status not in AGENT_INVALID_STATUSES and
|
||||
agent_models.AgentHeartBeat.is_active(agent)):
|
||||
guest = create_guest_client(context, id)
|
||||
try:
|
||||
instance.volume_used = guest.get_volume_info()['used']
|
||||
@ -319,8 +320,8 @@ class BaseInstance(SimpleInstance):
|
||||
def delete(self):
|
||||
if (self.db_info.server_status in ["BUILD"] and
|
||||
not self.db_info.task_status.is_error):
|
||||
raise exception.UnprocessableEntity("Instance %s is not ready."
|
||||
% self.id)
|
||||
raise exception.UnprocessableEntity("Instance %s is not ready." %
|
||||
self.id)
|
||||
LOG.debug(_(" ... deleting compute id = %s") %
|
||||
self.db_info.compute_instance_id)
|
||||
LOG.debug(_(" ... setting status to DELETING."))
|
||||
@ -402,13 +403,15 @@ class Instance(BuiltInstance):
|
||||
except nova_exceptions.NotFound:
|
||||
raise exception.FlavorNotFound(uuid=flavor_id)
|
||||
|
||||
db_info = DBInstance.create(name=name,
|
||||
flavor_id=flavor_id, tenant_id=context.tenant,
|
||||
volume_size=volume_size, task_status=InstanceTasks.BUILDING)
|
||||
db_info = DBInstance.create(name=name, flavor_id=flavor_id,
|
||||
tenant_id=context.tenant,
|
||||
volume_size=volume_size,
|
||||
task_status=InstanceTasks.BUILDING)
|
||||
LOG.debug(_("Tenant %s created new Reddwarf instance %s...")
|
||||
% (context.tenant, db_info.id))
|
||||
|
||||
service_status = InstanceServiceStatus.create(instance_id=db_info.id,
|
||||
service_status = InstanceServiceStatus.create(
|
||||
instance_id=db_info.id,
|
||||
status=ServiceStatuses.NEW)
|
||||
|
||||
dns_support = config.Config.get("reddwarf_dns_support", 'False')
|
||||
@ -419,7 +422,9 @@ class Instance(BuiltInstance):
|
||||
db_info.save()
|
||||
|
||||
task_api.API(context).create_instance(db_info.id, name, flavor_id,
|
||||
flavor.ram, image_id, databases, users, service_type, volume_size)
|
||||
flavor.ram, image_id, databases,
|
||||
users, service_type,
|
||||
volume_size)
|
||||
|
||||
return SimpleInstance(context, db_info, service_status)
|
||||
|
||||
@ -444,7 +449,8 @@ class Instance(BuiltInstance):
|
||||
self.update_db(task_status=InstanceTasks.RESIZING)
|
||||
LOG.debug("Instance %s set to RESIZING." % self.id)
|
||||
task_api.API(self.context).resize_flavor(self.id, new_flavor_id,
|
||||
old_flavor_size, new_flavor_size)
|
||||
old_flavor_size,
|
||||
new_flavor_size)
|
||||
|
||||
def resize_volume(self, new_size):
|
||||
self._validate_can_perform_action()
|
||||
@ -453,8 +459,9 @@ class Instance(BuiltInstance):
|
||||
raise exception.BadRequest("Instance %s has no volume." % self.id)
|
||||
old_size = self.volume_size
|
||||
if int(new_size) <= old_size:
|
||||
raise exception.BadRequest("The new volume 'size' must be larger "
|
||||
"than the current volume size of '%s'" % old_size)
|
||||
msg = ("The new volume 'size' must be larger than the current "
|
||||
"volume size of '%s'")
|
||||
raise exception.BadRequest(msg % old_size)
|
||||
# Set the task to Resizing before sending off to the taskmanager
|
||||
self.update_db(task_status=InstanceTasks.RESIZING)
|
||||
task_api.API(self.context).resize_volume(new_size, self.id)
|
||||
@ -481,12 +488,12 @@ class Instance(BuiltInstance):
|
||||
"""
|
||||
Raises exception if an instance action cannot currently be performed.
|
||||
"""
|
||||
if self.db_info.server_status != "ACTIVE" or \
|
||||
self.db_info.task_status != InstanceTasks.NONE or \
|
||||
not self.service_status.status.action_is_allowed:
|
||||
msg = "Instance is not currently available for an action to be " \
|
||||
"performed (status was %s)." % self.status
|
||||
LOG.error(msg)
|
||||
if any([self.db_info.server_status != "ACTIVE",
|
||||
self.db_info.task_status != InstanceTasks.NONE,
|
||||
not self.service_status.status.action_is_allowed]):
|
||||
msg = ("Instance is not currently available for an action to be "
|
||||
"performed (status was %s).")
|
||||
LOG.error(msg % self.status)
|
||||
raise exception.UnprocessableEntity(msg)
|
||||
|
||||
|
||||
@ -504,8 +511,8 @@ def create_server_list_matcher(server_list):
|
||||
instance_id=instance_id, server_id=server_id)
|
||||
else:
|
||||
# Should never happen, but never say never.
|
||||
LOG.error(_("Server %s for instance %s was found twice!")
|
||||
% (server_id, instance_id))
|
||||
LOG.error(_("Server %s for instance %s was found twice!") %
|
||||
(server_id, instance_id))
|
||||
raise exception.ReddwarfError(uuid=instance_id)
|
||||
return find_server
|
||||
|
||||
@ -664,9 +671,13 @@ class ServiceStatus(object):
|
||||
|
||||
@property
|
||||
def action_is_allowed(self):
|
||||
return self._code in [ServiceStatuses.RUNNING._code,
|
||||
ServiceStatuses.SHUTDOWN._code, ServiceStatuses.CRASHED._code,
|
||||
ServiceStatuses.BLOCKED._code]
|
||||
allowed_statuses = [
|
||||
ServiceStatuses.RUNNING._code,
|
||||
ServiceStatuses.SHUTDOWN._code,
|
||||
ServiceStatuses.CRASHED._code,
|
||||
ServiceStatuses.BLOCKED._code,
|
||||
]
|
||||
return self._code in allowed_statuses
|
||||
|
||||
@property
|
||||
def api_status(self):
|
||||
|
@ -216,8 +216,9 @@ class InstanceController(wsgi.Controller):
|
||||
image_id, databases, users,
|
||||
service_type, volume_size)
|
||||
|
||||
return wsgi.Result(views.InstanceDetailView(instance, req=req,
|
||||
add_volumes=self.add_volumes).data(), 200)
|
||||
view = views.InstanceDetailView(instance, req=req,
|
||||
add_volumes=self.add_volumes)
|
||||
return wsgi.Result(view.data(), 200)
|
||||
|
||||
@staticmethod
|
||||
def _validate_body_not_empty(body):
|
||||
@ -267,11 +268,9 @@ class InstanceController(wsgi.Controller):
|
||||
body['instance']
|
||||
body['instance']['flavorRef']
|
||||
vol_enabled = utils.bool_from_string(
|
||||
config.Config.get('reddwarf_volume_support',
|
||||
'True'))
|
||||
config.Config.get('reddwarf_volume_support', 'True'))
|
||||
must_have_vol = utils.bool_from_string(
|
||||
config.Config.get('reddwarf_must_use_volume',
|
||||
'False'))
|
||||
config.Config.get('reddwarf_must_use_volume', 'False'))
|
||||
if vol_enabled:
|
||||
if body['instance'].get('volume', None):
|
||||
if body['instance']['volume'].get('size', None):
|
||||
|
@ -67,12 +67,14 @@ class InstanceTasks(object):
|
||||
RESIZING = InstanceTask(0x04, 'RESIZING', 'Resizing the instance.')
|
||||
BUILDING = InstanceTask(0x05, 'BUILDING', 'The instance is building.')
|
||||
|
||||
BUILDING_ERROR_DNS = InstanceTask(0x50, 'BUILDING',
|
||||
'Build error: DNS.', is_error=True)
|
||||
BUILDING_ERROR_DNS = InstanceTask(0x50, 'BUILDING', 'Build error: DNS.',
|
||||
is_error=True)
|
||||
BUILDING_ERROR_SERVER = InstanceTask(0x51, 'BUILDING',
|
||||
'Build error: Server.', is_error=True)
|
||||
'Build error: Server.',
|
||||
is_error=True)
|
||||
BUILDING_ERROR_VOLUME = InstanceTask(0x52, 'BUILDING',
|
||||
'Build error: Volume.', is_error=True)
|
||||
'Build error: Volume.',
|
||||
is_error=True)
|
||||
|
||||
|
||||
# Dissuade further additions at run-time.
|
||||
|
@ -25,13 +25,13 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_ip_address(addresses):
|
||||
if addresses is not None and \
|
||||
addresses.get('private') is not None and \
|
||||
len(addresses['private']) > 0:
|
||||
if all([addresses is not None,
|
||||
addresses.get('private') is not None,
|
||||
len(addresses['private']) > 0]):
|
||||
return [addr.get('addr') for addr in addresses['private']]
|
||||
if addresses is not None and\
|
||||
addresses.get('usernet') is not None and\
|
||||
len(addresses['usernet']) > 0:
|
||||
if all([addresses is not None,
|
||||
addresses.get('usernet') is not None,
|
||||
len(addresses['usernet']) > 0]):
|
||||
return [addr.get('addr') for addr in addresses['usernet']]
|
||||
|
||||
|
||||
@ -100,8 +100,8 @@ class InstanceDetailView(InstanceView):
|
||||
if ip is not None and len(ip) > 0:
|
||||
result['instance']['ip'] = ip
|
||||
if self.add_volumes:
|
||||
if isinstance(self.instance, models.DetailInstance) and \
|
||||
self.instance.volume_used:
|
||||
if (isinstance(self.instance, models.DetailInstance) and
|
||||
self.instance.volume_used):
|
||||
used = self._to_gb(self.instance.volume_used)
|
||||
result['instance']['volume']['used'] = used
|
||||
return result
|
||||
|
@ -253,8 +253,8 @@ class ExtensionMiddleware(wsgi.Middleware):
|
||||
return request_ext_resources
|
||||
|
||||
def __init__(self, application, config, ext_mgr=None):
|
||||
ext_mgr = ext_mgr or ExtensionManager(
|
||||
config['api_extensions_path'])
|
||||
ext_mgr = (ext_mgr or
|
||||
ExtensionManager(config['api_extensions_path']))
|
||||
mapper = routes.Mapper()
|
||||
|
||||
# extended resources
|
||||
|
@ -55,13 +55,17 @@ class FreshInstanceTasks(FreshInstance):
|
||||
def create_instance(self, flavor_id, flavor_ram, image_id,
|
||||
databases, users, service_type, volume_size):
|
||||
if use_nova_server_volume:
|
||||
server, volume_info = self._create_server_volume(flavor_id,
|
||||
image_id, service_type,
|
||||
server, volume_info = self._create_server_volume(
|
||||
flavor_id,
|
||||
image_id,
|
||||
service_type,
|
||||
volume_size)
|
||||
else:
|
||||
server, volume_info = self._create_server_volume_individually(
|
||||
flavor_id, image_id,
|
||||
service_type, volume_size)
|
||||
flavor_id,
|
||||
image_id,
|
||||
service_type,
|
||||
volume_size)
|
||||
try:
|
||||
self._create_dns_entry()
|
||||
except Exception as e:
|
||||
@ -153,12 +157,14 @@ class FreshInstanceTasks(FreshInstance):
|
||||
|
||||
volume_support = config.Config.get("reddwarf_volume_support", 'False')
|
||||
LOG.debug(_("reddwarf volume support = %s") % volume_support)
|
||||
if volume_size is None or \
|
||||
utils.bool_from_string(volume_support) is False:
|
||||
volume_info = {'block_device': None,
|
||||
if (volume_size is None or
|
||||
utils.bool_from_string(volume_support) is False):
|
||||
volume_info = {
|
||||
'block_device': None,
|
||||
'device_path': None,
|
||||
'mount_point': None,
|
||||
'volumes': None}
|
||||
'volumes': None,
|
||||
}
|
||||
return volume_info
|
||||
|
||||
volume_client = create_nova_volume_client(self.context)
|
||||
@ -209,8 +215,10 @@ class FreshInstanceTasks(FreshInstance):
|
||||
files = {"/etc/guest_info": "guest_id=%s\nservice_type=%s\n" %
|
||||
(self.id, service_type)}
|
||||
name = self.hostname or self.name
|
||||
bdmap = block_device_mapping
|
||||
server = nova_client.servers.create(name, image_id, flavor_id,
|
||||
files=files, block_device_mapping=block_device_mapping)
|
||||
files=files,
|
||||
block_device_mapping=bdmap)
|
||||
LOG.debug(_("Created new compute instance %s.") % server.id)
|
||||
return server
|
||||
|
||||
@ -240,14 +248,14 @@ class FreshInstanceTasks(FreshInstance):
|
||||
LOG.info("Polling for ip addresses: $%s " % server.addresses)
|
||||
if server.addresses != {}:
|
||||
return True
|
||||
elif server.addresses == {} and\
|
||||
server.status != InstanceStatus.ERROR:
|
||||
elif (server.addresses == {} and
|
||||
server.status != InstanceStatus.ERROR):
|
||||
return False
|
||||
elif server.addresses == {} and\
|
||||
server.status == InstanceStatus.ERROR:
|
||||
LOG.error(_("Instance IP not available, instance (%s): "
|
||||
elif (server.addresses == {} and
|
||||
server.status == InstanceStatus.ERROR):
|
||||
msg = _("Instance IP not available, instance (%s): "
|
||||
"server had status (%s).")
|
||||
% (self.id, server.status))
|
||||
LOG.error(msg % (self.id, server.status))
|
||||
raise ReddwarfError(status=server.status)
|
||||
poll_until(get_server, ip_is_available,
|
||||
sleep_time=1, time_out=60 * 2)
|
||||
@ -348,10 +356,10 @@ class BuiltInstanceTasks(BuiltInstance):
|
||||
|
||||
# Do initial check and confirm the status is appropriate.
|
||||
self._refresh_compute_server_info()
|
||||
if self.server.status != "RESIZE" and\
|
||||
self.server.status != "VERIFY_RESIZE":
|
||||
raise ReddwarfError("Unexpected status after " \
|
||||
"call to resize! : %s" % resize_status_msg())
|
||||
if (self.server.status != "RESIZE" and
|
||||
self.server.status != "VERIFY_RESIZE"):
|
||||
msg = "Unexpected status after call to resize! : %s"
|
||||
raise ReddwarfError(msg % resize_status_msg())
|
||||
|
||||
# Wait for the flavor to change.
|
||||
def update_server_info():
|
||||
@ -366,9 +374,10 @@ class BuiltInstanceTasks(BuiltInstance):
|
||||
# Do check to make sure the status and flavor id are correct.
|
||||
if (str(self.server.flavor['id']) != str(new_flavor_id) or
|
||||
self.server.status != "VERIFY_RESIZE"):
|
||||
raise ReddwarfError("Assertion failed! flavor_id=%s "
|
||||
"and not %s"
|
||||
% (str(self.server.flavor['id']), str(new_flavor_id)))
|
||||
msg = "Assertion failed! flavor_id=%s and not %s"
|
||||
actual_flavor = self.server.flavor['id']
|
||||
expected_flavor = new_flavor_id
|
||||
raise ReddwarfError(msg % (actual_flavor, expected_flavor))
|
||||
|
||||
# Confirm the resize with Nova.
|
||||
LOG.debug("Instance %s calling Compute confirm resize..."
|
||||
|
@ -56,8 +56,10 @@ class BaseTest(unittest.TestCase):
|
||||
self.maxDiff = None
|
||||
|
||||
self.mock = mox.Mox()
|
||||
conf, reddwarf_app = config.Config.load_paste_app('reddwarfapp',
|
||||
{"config_file": test_config_file()}, None)
|
||||
conf, reddwarf_app = config.Config.load_paste_app(
|
||||
'reddwarfapp',
|
||||
{"config_file": test_config_file()},
|
||||
None)
|
||||
db_api.configure_db(conf)
|
||||
db_api.clean_db()
|
||||
super(BaseTest, self).setUp()
|
||||
@ -73,19 +75,18 @@ class BaseTest(unittest.TestCase):
|
||||
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
self.fail("Expected {0} to raise {1}".format(func,
|
||||
repr(exception)))
|
||||
self.fail("Expected %r to raise %r" % (func, exception))
|
||||
except exception as error:
|
||||
self.assertIn(message, str(error))
|
||||
|
||||
def assertIn(self, expected, actual):
|
||||
"""This is similar to assertIn in python 2.7"""
|
||||
self.assertTrue(expected in actual,
|
||||
"{0} does not contain {1}".format(repr(actual), repr(expected)))
|
||||
"%r does not contain %r" % (actual, expected))
|
||||
|
||||
def assertNotIn(self, expected, actual):
|
||||
self.assertFalse(expected in actual,
|
||||
"{0} does contains {1}".format(repr(actual), repr(expected)))
|
||||
"%r does not contain %r" % (actual, expected))
|
||||
|
||||
def assertIsNone(self, actual):
|
||||
"""This is similar to assertIsNone in python 2.7"""
|
||||
@ -99,14 +100,16 @@ class BaseTest(unittest.TestCase):
|
||||
self.assertEqual(sorted(expected), sorted(actual))
|
||||
|
||||
def assertModelsEqual(self, expected, actual):
|
||||
self.assertEqual(sorted(expected, key=lambda model: model.id),
|
||||
self.assertEqual(
|
||||
sorted(expected, key=lambda model: model.id),
|
||||
sorted(actual, key=lambda model: model.id))
|
||||
|
||||
def assertUrlEqual(self, expected, actual):
|
||||
self.assertEqual(expected.partition("?")[0], actual.partition("?")[0])
|
||||
|
||||
#params ordering might be different in the urls
|
||||
self.assertEqual(urlparse.parse_qs(expected.partition("?")[2]),
|
||||
self.assertEqual(
|
||||
urlparse.parse_qs(expected.partition("?")[2]),
|
||||
urlparse.parse_qs(actual.partition("?")[2]))
|
||||
|
||||
def assertErrorResponse(self, response, error_type, expected_error):
|
||||
|
@ -38,11 +38,10 @@ class FakeFlavor(object):
|
||||
|
||||
@property
|
||||
def links(self):
|
||||
return [{
|
||||
"href": "http://localhost:8774/v2/"
|
||||
"5064d71eb09c47e1956cf579822bae9a/flavors/%s" % self.id,
|
||||
"rel": link_type
|
||||
} for link_type in ['self', 'bookmark']]
|
||||
url = ("http://localhost:8774/v2/5064d71eb09c47e1956cf579822bae9a/"
|
||||
"flavors/%s") % self.id
|
||||
return [{"href": url, "rel": link_type}
|
||||
for link_type in ['self', 'bookmark']]
|
||||
|
||||
@property
|
||||
def href_suffix(self):
|
||||
@ -151,10 +150,9 @@ class FakeServer(object):
|
||||
|
||||
@property
|
||||
def links(self):
|
||||
return [{
|
||||
"href": "https://localhost:9999/v1.0/1234/instances/%s" % self.id,
|
||||
"rel": link_type
|
||||
} for link_type in ['self', 'bookmark']]
|
||||
url = "https://localhost:9999/v1.0/1234/instances/%s" % self.id
|
||||
return [{"href": url, "rel": link_type}
|
||||
for link_type in ['self', 'bookmark']]
|
||||
|
||||
def resize(self, new_flavor_id):
|
||||
self._current_status = "RESIZE"
|
||||
@ -212,8 +210,8 @@ class FakeServers(object):
|
||||
def can_see(self, id):
|
||||
"""Can this FakeServers, with its context, see some resource?"""
|
||||
server = self.db[id]
|
||||
return self.context.is_admin or \
|
||||
server.owner.tenant == self.context.tenant
|
||||
return (self.context.is_admin or
|
||||
server.owner.tenant == self.context.tenant)
|
||||
|
||||
def create(self, name, image_id, flavor_ref, files=None,
|
||||
block_device_mapping=None, volume=None):
|
||||
@ -253,8 +251,8 @@ class FakeServers(object):
|
||||
mapping = block_device_mapping[device]
|
||||
(id, _type, size, delete_on_terminate) = mapping.split(":")
|
||||
volume = self.volumes.get(id)
|
||||
volume.mapping = FakeBlockDeviceMappingInfo(id, device,
|
||||
_type, size, delete_on_terminate)
|
||||
volume.mapping = FakeBlockDeviceMappingInfo(
|
||||
id, device, _type, size, delete_on_terminate)
|
||||
volumes.append(volume)
|
||||
return volumes
|
||||
|
||||
@ -359,10 +357,11 @@ class FakeVolume(object):
|
||||
self.device = "/var/lib/mysql"
|
||||
|
||||
def __repr__(self):
|
||||
return ("FakeVolume(id=%s, size=%s, "
|
||||
"display_name=%s, display_description=%s, _current_status=%s)"
|
||||
% (self.id, self.size, self.display_name,
|
||||
self.display_description, self._current_status))
|
||||
msg = ("FakeVolume(id=%s, size=%s, display_name=%s, "
|
||||
"display_description=%s, _current_status=%s)")
|
||||
params = (self.id, self.size, self.display_name,
|
||||
self.display_description, self._current_status)
|
||||
return (msg % params)
|
||||
|
||||
@property
|
||||
def availability_zone(self):
|
||||
@ -417,8 +416,8 @@ class FakeVolumes(object):
|
||||
def can_see(self, id):
|
||||
"""Can this FakeVolumes, with its context, see some resource?"""
|
||||
server = self.db[id]
|
||||
return self.context.is_admin or \
|
||||
server.owner.tenant == self.context.tenant
|
||||
return (self.context.is_admin or
|
||||
server.owner.tenant == self.context.tenant)
|
||||
|
||||
def get(self, id):
|
||||
if id not in self.db:
|
||||
|
@ -40,9 +40,14 @@ class ContextTest(unittest.TestCase):
|
||||
self.assertEqual(ctx_dict['auth_tok'], AUTH_TOK)
|
||||
|
||||
def test_creating_context(self):
|
||||
tmp_ctx_dict = {'user': USER, 'tenant': TENANT, 'is_admin': True,
|
||||
'show_deleted': True, 'read_only': True,
|
||||
'auth_tok': AUTH_TOK}
|
||||
tmp_ctx_dict = {
|
||||
'user': USER,
|
||||
'tenant': TENANT,
|
||||
'is_admin': True,
|
||||
'show_deleted': True,
|
||||
'read_only': True,
|
||||
'auth_tok': AUTH_TOK,
|
||||
}
|
||||
tmp_ctx = context.ReddwarfContext.from_dict(tmp_ctx_dict)
|
||||
self.assertEqual(tmp_ctx.user, USER)
|
||||
self.assertEqual(tmp_ctx.tenant, TENANT)
|
||||
|
@ -46,21 +46,23 @@ class TestInstance(tests.BaseTest):
|
||||
self.FAKE_SERVER.id = self.expected_id
|
||||
self.FAKE_SERVER.flavor = ('http://localhost/1234/flavors/',
|
||||
'52415800-8b69-11e0-9b19-734f1195ff37')
|
||||
self.FAKE_SERVER.links = [{
|
||||
self.FAKE_SERVER.links = [
|
||||
{
|
||||
"href": "http://localhost/1234/instances/123",
|
||||
"rel": "self"
|
||||
"rel": "self",
|
||||
},
|
||||
{
|
||||
"href": "http://localhost/1234/instances/123",
|
||||
"rel": "bookmark"
|
||||
}]
|
||||
"rel": "bookmark",
|
||||
},
|
||||
]
|
||||
self.FAKE_SERVER.addresses = {
|
||||
"private": [
|
||||
{
|
||||
"addr": "10.0.0.4",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
client = self.mock.CreateMock(novaclient.v1_1.Client)
|
||||
|
@ -33,22 +33,26 @@ class ControllerTestBase(tests.BaseTest):
|
||||
|
||||
def setUp(self):
|
||||
super(ControllerTestBase, self).setUp()
|
||||
conf, reddwarf_app = config.Config.load_paste_app('reddwarfapp',
|
||||
{"config_file": tests.test_config_file()}, None)
|
||||
conf, reddwarf_app = config.Config.load_paste_app(
|
||||
'reddwarfapp',
|
||||
{"config_file": tests.test_config_file()},
|
||||
None)
|
||||
self.app = unit.TestApp(reddwarf_app)
|
||||
|
||||
|
||||
class TestInstanceController(ControllerTestBase):
|
||||
|
||||
DUMMY_INSTANCE_ID = "123"
|
||||
DUMMY_INSTANCE = {"id": DUMMY_INSTANCE_ID,
|
||||
DUMMY_INSTANCE = {
|
||||
"id": DUMMY_INSTANCE_ID,
|
||||
"name": "DUMMY_NAME",
|
||||
"status": "BUILD",
|
||||
"created": "createtime",
|
||||
"updated": "updatedtime",
|
||||
"flavor": {},
|
||||
"links": [],
|
||||
"addresses": {}}
|
||||
"addresses": {},
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
self.instances_path = "/tenant/instances"
|
||||
@ -98,21 +102,23 @@ class TestInstanceController(ControllerTestBase):
|
||||
self.FAKE_SERVER.created = utils.utcnow()
|
||||
self.FAKE_SERVER.id = utils.generate_uuid()
|
||||
self.FAKE_SERVER.flavor = 'http://localhost/1234/flavors/1234'
|
||||
self.FAKE_SERVER.links = [{
|
||||
self.FAKE_SERVER.links = [
|
||||
{
|
||||
"href": "http://localhost/1234/instances/123",
|
||||
"rel": "self"
|
||||
"rel": "self",
|
||||
},
|
||||
{
|
||||
"href": "http://localhost/1234/instances/123",
|
||||
"rel": "bookmark"
|
||||
}]
|
||||
"rel": "bookmark",
|
||||
}
|
||||
]
|
||||
self.FAKE_SERVER.addresses = {
|
||||
"private": [
|
||||
{
|
||||
"addr": "10.0.0.4",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
"version": 4,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
client = self.mock.CreateMock(novaclient.v1_1.Client)
|
||||
@ -131,8 +137,8 @@ class TestInstanceController(ControllerTestBase):
|
||||
models.Instance.data().AndReturn(self.DUMMY_INSTANCE)
|
||||
|
||||
self.mock.StubOutWithMock(models.ServiceImage, 'find_by')
|
||||
models.ServiceImage.find_by(service_name=mox.IgnoreArg()).AndReturn(
|
||||
{'image_id': 1234})
|
||||
models.ServiceImage.find_by(
|
||||
service_name=mox.IgnoreArg()).AndReturn({'image_id': 1234})
|
||||
|
||||
self.mock_out_client_create()
|
||||
self.mock.ReplayAll()
|
||||
@ -154,7 +160,6 @@ class TestInstanceController(ControllerTestBase):
|
||||
}
|
||||
}
|
||||
response = self.app.post_json("%s" % (self.instances_path), body=body,
|
||||
headers={'X-Auth-Token': '123'},
|
||||
)
|
||||
headers={'X-Auth-Token': '123'})
|
||||
print(response)
|
||||
self.assertEqual(response.status_int, 201)
|
||||
|
@ -38,8 +38,11 @@ class VersionsController(wsgi.Controller):
|
||||
"""Respond to a request for API versions."""
|
||||
versions = []
|
||||
for key, data in VERSIONS.items():
|
||||
v = BaseVersion(data["id"], data["status"],
|
||||
request.application_url, data["updated"])
|
||||
v = BaseVersion(
|
||||
data["id"],
|
||||
data["status"],
|
||||
request.application_url,
|
||||
data["updated"])
|
||||
versions.append(v)
|
||||
return wsgi.Result(VersionsDataView(versions))
|
||||
|
||||
@ -60,10 +63,12 @@ class BaseVersion(object):
|
||||
self.updated = updated
|
||||
|
||||
def data(self):
|
||||
return dict(id=self.id,
|
||||
status=self.status,
|
||||
updated=self.updated,
|
||||
links=[dict(rel="self", href=self.url())])
|
||||
return {
|
||||
"id": self.id,
|
||||
"status": self.status,
|
||||
"updated": self.updated,
|
||||
"links": [{"rel": "self", "href": self.url()}],
|
||||
}
|
||||
|
||||
def url(self):
|
||||
url = os.path.join(self.base_url, self.id)
|
||||
|
Loading…
Reference in New Issue
Block a user