Author: tomaz
Date: Wed Oct 31 18:47:28 2012
New Revision: 1404292
URL: http://svn.apache.org/viewvc?rev=1404292&view=rev
Log:
Multiple improvements and additions in the vCloud driver:
- Expose generic query method (ex_query)
- Provide functionality to get and set control access for vApps. This way
created vApps can be shared between users/groups or everyone.
Contributed by Michal Galet, part of LIBCLOUD-251.
Added:
libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml
libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml
libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml
libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml
Modified:
libcloud/trunk/CHANGES
libcloud/trunk/libcloud/compute/drivers/vcloud.py
libcloud/trunk/libcloud/test/compute/test_vcloud.py
Modified: libcloud/trunk/CHANGES
URL: http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1404292&r1=1404291&r2=1404292&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Wed Oct 31 18:47:28 2012
@@ -25,6 +25,13 @@ Changes with Apache Libcloud in developm
TODO.
[Tomaz Muraus]
+ - Improvements and additions in vCloud driver:
+
+ - Expose generic query method (ex_query)
+ - Provide functionality to get and set control access for vApps. This way
+ created vApps can be shared between users/groups or everyone.
+ [Michal Galet]
+
*) DNS
- Update 'if type' checks in the update_record methods to behave correctly
Modified: libcloud/trunk/libcloud/compute/drivers/vcloud.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/vcloud.py?rev=1404292&r1=1404291&r2=1404292&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/vcloud.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/vcloud.py Wed Oct 31 18:47:28 2012
@@ -20,7 +20,9 @@ import sys
import re
import base64
import os
+import urllib
from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import urlencode
from libcloud.utils.py3 import urlparse
from libcloud.utils.py3 import b
from libcloud.utils.py3 import next
@@ -71,8 +73,10 @@ def get_url_path(url):
return urlparse(url.strip()).path
-class Vdc:
- """Virtual datacenter (vDC) representation"""
+class Vdc(object):
+ """
+ Virtual datacenter (vDC) representation
+ """
def __init__(self, id, name, driver, allocation_model=None, cpu=None,
memory=None, storage=None):
@@ -85,22 +89,61 @@ class Vdc:
self.storage = storage
def __repr__(self):
- return (('<Vdc: id=%s, name=%s, driver=%s ...>')
+ return ('<Vdc: id=%s, name=%s, driver=%s ...>'
% (self.id, self.name, self.driver.name))
-class Capacity:
- """Represents CPU, Memory or Storage capacity of vDC."""
+class Capacity(object):
+ """
+ Represents CPU, Memory or Storage capacity of vDC.
+ """
def __init__(self, limit, used, units):
self.limit = limit
self.used = used
self.units = units
def __repr__(self):
- return (('<Capacity: limit=%s, used=%s, units=%s>')
+ return ('<Capacity: limit=%s, used=%s, units=%s>'
% (self.limit, self.used, self.units))
+class ControlAccess(object):
+ """
+ Represents control access settings of a node
+ """
+
+ class AccessLevel(object):
+ READ_ONLY = 'ReadOnly'
+ CHANGE = 'Change'
+ FULL_CONTROL = 'FullControl'
+
+ def __init__(self, node, everyone_access_level, subjects=None):
+ self.node = node
+ self.everyone_access_level = everyone_access_level
+ if not subjects:
+ subjects = []
+ self.subjects = subjects
+
+ def __repr__(self):
+ return ('<ControlAccess: node=%s, everyone_access_level=%s, subjects=%s>'
+ % (self.node, self.everyone_access_level, self.subjects))
+
+
+class Subject(object):
+ """
+ User or group subject
+ """
+ def __init__(self, type, name, access_level, id=None):
+ self.type = type
+ self.name = name
+ self.access_level = access_level
+ self.id = id
+
+ def __repr__(self):
+ return ('<Subject: type=%s, name=%s, access_level=%s>'
+ % (self.type, self.name, self.access_level))
+
+
class InstantiateVAppXML(object):
def __init__(self, name, template, net_href, cpus, memory,
password=None, row=None, group=None):
@@ -122,14 +165,14 @@ class InstantiateVAppXML(object):
self.root = self._make_instantiation_root()
self._add_vapp_template(self.root)
- instantionation_params = ET.SubElement(self.root,
+ instantiation_params = ET.SubElement(self.root,
"InstantiationParams")
# product and virtual hardware
- self._make_product_section(instantionation_params)
- self._make_virtual_hardware(instantionation_params)
+ self._make_product_section(instantiation_params)
+ self._make_virtual_hardware(instantiation_params)
- network_config_section = ET.SubElement(instantionation_params,
+ network_config_section = ET.SubElement(instantiation_params,
"NetworkConfigSection")
network_config = ET.SubElement(network_config_section,
@@ -818,34 +861,37 @@ class Instantiate_1_5_VAppXML(object):
def _build_xmltree(self):
self.root = self._make_instantiation_root()
- if self.network:
- instantionation_params = ET.SubElement(self.root, "InstantiationParams")
- network_config_section = ET.SubElement(instantionation_params, "NetworkConfigSection")
+ if self.network is not None:
+ instantionation_params = ET.SubElement(self.root,
+ 'InstantiationParams')
+ network_config_section = ET.SubElement(instantionation_params,
+ 'NetworkConfigSection')
ET.SubElement(
network_config_section,
- "Info",
- {'xmlns': "http://schemas.dmtf.org/ovf/envelope/1"}
+ 'Info',
+ {'xmlns': 'http://schemas.dmtf.org/ovf/envelope/1'}
)
- network_config = ET.SubElement(network_config_section, "NetworkConfig")
+ network_config = ET.SubElement(network_config_section,
+ 'NetworkConfig')
self._add_network_association(network_config)
self._add_vapp_template(self.root)
def _make_instantiation_root(self):
return ET.Element(
- "InstantiateVAppTemplateParams",
+ 'InstantiateVAppTemplateParams',
{'name': self.name,
'deploy': 'false',
'powerOn': 'false',
'xml:lang': 'en',
- 'xmlns': "http://www.vmware.com/vcloud/v1.5",
- 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"}
+ 'xmlns': 'http://www.vmware.com/vcloud/v1.5',
+ 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
)
def _add_vapp_template(self, parent):
return ET.SubElement(
parent,
- "Source",
+ 'Source',
{'href': self.template}
)
@@ -857,9 +903,12 @@ class Instantiate_1_5_VAppXML(object):
# Set a custom vApp VM network name
parent.set('networkName', self.vm_network)
configuration = ET.SubElement(parent, 'Configuration')
- ET.SubElement(configuration, 'ParentNetwork', {'href': self.network.get('href')})
+ ET.SubElement(configuration, 'ParentNetwork',
+ {'href': self.network.get('href')})
+
if self.vm_fence is None:
- fencemode = self.network.find(fixxpath(self.network, 'Configuration/FenceMode')).text
+ fencemode = self.network.find(fixxpath(self.network,
+ 'Configuration/FenceMode')).text
else:
fencemode = self.vm_fence
ET.SubElement(configuration, 'FenceMode').text = fencemode
@@ -1047,6 +1096,145 @@ class VCloud_1_5_NodeDriver(VCloudNodeDr
res = self.connection.request(get_url_path(node.id))
return self._to_node(res.object)
+ def ex_get_control_access(self, node):
+ """
+ Returns the control access settings for specified node.
+
+ @param node: node to get the control access for
+ @type node: L{Node}
+
+ @rtype: L{ControlAccess}
+ """
+ res = self.connection.request(
+ '%s/controlAccess' % get_url_path(node.id))
+ everyone_access_level = None
+ is_shared_elem = res.object.find(
+ fixxpath(res.object, "IsSharedToEveryone"))
+ if is_shared_elem is not None and is_shared_elem.text == 'true':
+ everyone_access_level = res.object.find(
+ fixxpath(res.object, "EveryoneAccessLevel")).text
+
+ # Parse all subjects
+ subjects = []
+ for elem in res.object.findall(
+ fixxpath(res.object, "AccessSettings/AccessSetting")):
+ access_level = elem.find(fixxpath(res.object, "AccessLevel")).text
+ subject_elem = elem.find(fixxpath(res.object, "Subject"))
+ if subject_elem.get('type') == 'application/vnd.vmware.admin.group+xml':
+ subj_type = 'group'
+ else:
+ subj_type = 'user'
+ res = self.connection.request(get_url_path(subject_elem.get('href')))
+ name = res.object.get('name')
+ subject = Subject(type=subj_type,
+ name=name,
+ access_level=access_level,
+ id=subject_elem.get('href'))
+ subjects.append(subject)
+
+ return ControlAccess(node, everyone_access_level, subjects)
+
+ def ex_set_control_access(self, node, control_access):
+ """
+ Sets control access for the specified node.
+
+ @param node: node
+ @type node: L{Node}
+
+ @param control_access: control access settings
+ @type control_access: L{ControlAccess}
+
+ @rtype: C{None}
+ """
+ xml = ET.Element('ControlAccessParams',
+ {'xmlns': 'http://www.vmware.com/vcloud/v1.5'})
+ shared_to_everyone = ET.SubElement(xml, 'IsSharedToEveryone')
+ if control_access.everyone_access_level:
+ shared_to_everyone.text = 'true'
+ everyone_access_level = ET.SubElement(xml, 'EveryoneAccessLevel')
+ everyone_access_level.text = control_access.everyone_access_level
+ else:
+ shared_to_everyone.text = 'false'
+
+ # Set subjects
+ if control_access.subjects:
+ access_settings_elem = ET.SubElement(xml, 'AccessSettings')
+ for subject in control_access.subjects:
+ setting = ET.SubElement(access_settings_elem, 'AccessSetting')
+ if subject.id:
+ href = subject.id
+ else:
+ res = self.ex_query(type=subject.type, filter='name==' + subject.name)
+ if not res:
+ raise LibcloudError('Specified subject "%s %s" not found '
+ % (subject.type, subject.name))
+ href = res[0]['href']
+ ET.SubElement(setting, 'Subject', {'href': href})
+ ET.SubElement(setting, 'AccessLevel').text = subject.access_level
+
+ self.connection.request(
+ '%s/action/controlAccess' % get_url_path(node.id),
+ data=ET.tostring(xml),
+ headers={
+ 'Content-Type': 'application/vnd.vmware.vcloud.controlAccess+xml'
+ },
+ method='POST')
+
+ def ex_query(self, type, filter=None, page=1, page_size=100, sort_asc=None,
+ sort_desc=None):
+ """
+ Queries vCloud for specified type. See http://www.vmware.com/pdf/vcd_15_api_guide.pdf
+ for details. Each element of the returned list is a dictionary with all
+ attributes from the record.
+
+ @param type: type to query (r.g. user, group, vApp etc.)
+ @type type: C{str}
+
+ @param filter: filter expression (see documentation for syntax)
+ @type filter: C{str}
+
+ @param page: page number
+ @type page: C{int}
+
+ @param page_size: page size
+ @type page_size: C{int}
+
+ @param sort_asc: sort in ascending order by specified field
+ @type sort_asc: C{str}
+
+ @param sort_desc: sort in descending order by specified field
+ @type sort_desc: C{str}
+
+ @rtype: C{list} of dict
+ """
+ # This is a workaround for filter parameter encoding
+ # the urllib encodes (name==Developers%20Only) into
+ # %28name%3D%3DDevelopers%20Only%29) which is not accepted by vCloud
+ params = {
+ 'type': type,
+ 'pageSize': page_size,
+ 'page': page,
+ }
+ if sort_asc:
+ params['sortAsc'] = sort_asc
+ if sort_desc:
+ params['sortDesc'] = sort_desc
+
+ url = '/api/query?' + urlencode(params)
+ if filter:
+ if not filter.startswith('('):
+ filter = '(' + filter + ')'
+ url += '&filter=' + filter.replace(' ', '+')
+
+ results = []
+ res = self.connection.request(url)
+ for elem in res.object:
+ if not elem.tag.endswith('Link'):
+ result = elem.attrib
+ result['type'] = elem.tag.split('}')[1]
+ results.append(result)
+ return results
+
def create_node(self, **kwargs):
"""Creates and returns node. If the source image is:
- vApp template - a new vApp is instantiated from template
@@ -1612,7 +1800,10 @@ class VCloud_1_5_NodeDriver(VCloudNodeDr
'name': vm_elem.get('name'),
'state': self.NODE_STATE_MAP[vm_elem.get('status')],
'public_ips': public_ips,
- 'private_ips': private_ips
+ 'private_ips': private_ips,
+ 'os_type': vm_elem
+ .find('{http://schemas.dmtf.org/ovf/envelope/1}OperatingSystemSection')
+ .get('{http://www.vmware.com/schema/ovf}osType')
}
vms.append(vm)
Added: libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml?rev=1404292&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml
(added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml
Wed Oct 31 18:47:28 2012
@@ -0,0 +1,11 @@
+<Group name="MyGroup" id="urn:vcloud:group:b8202c48-7151-4e61-9a6c-155474c7d413" type="application/vnd.vmware.admin.group+xml"
href="https://vm-vcloud/api/admin/group/b8202c48-7151-4e61-9a6c-155474c7d413" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5
http://66.69.64.27/api/v1.5/schema/master.xsd" xmlns="http://www.vmware.com/vcloud/v1.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <Link rel="edit" type="application/vnd.vmware.admin.group+xml" href="https://vm-vcloud/api/admin/group/b8202c48-7151-4e61-9a6c-155474c7d413"/>
+ <Link rel="remove" href="https://vm-vcloud/api/admin/group/b8202c48-7151-4e61-9a6c-155474c7d413"/>
+ <Description/>
+ <NameInSource>\CF\CB\AD\5D\1D\34\09\4D\A4\77\8D\A3\CA\99\75\FB</NameInSource>
+ <UsersList>
+ <UserReference type="application/vnd.vmware.admin.user+xml" name="jrambo" href="https://vm-vcloud/api/admin/user/1f588aa4-2fce-4f64-9c24-46b525236ced"/>
+ <UserReference type="application/vnd.vmware.admin.user+xml" name="user2" href="https://vm-vcloud/api/admin/user/bf3d9ba7-074d-4adf-b13d-18605f04f5f7"/>
+ </UsersList>
+ <Role type="application/vnd.vmware.admin.role+xml" name="Viewer" href="https://vm-vcloud/api/admin/role/58247cd9-cd51-45db-b184-f824d3d0a655"/>
+</Group>
\ No newline at end of file
Added: libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml?rev=1404292&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml (added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml Wed Oct 31
18:47:28 2012
@@ -0,0 +1,5 @@
+<QueryResultRecords total="1" pageSize="100" page="1" name="group" type="application/vnd.vmware.vcloud.query.records+xml"
href="https://vm-vcloud/api/query?type=group&page=1&pageSize=100&format=records&filter=(name==MyGroup)"
xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://66.67.64.27/api/v1.5/schema/master.xsd"
xmlns="http://www.vmware.com/vcloud/v1.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <Link rel="alternate" type="application/vnd.vmware.vcloud.query.references+xml" href="https://vm-vcloud/api/query?type=group&page=1&pageSize=100&format=references&filter=(name==MyGroup)"/>
+ <Link rel="alternate" type="application/vnd.vmware.vcloud.query.idrecords+xml" href="https://vm-vcloud/api/query?type=group&page=1&pageSize=100&format=idrecords&filter=(name==MyGroup)"/>
+ <GroupRecord roleName="Viewer" name="MyGroup" isReadOnly="false" href="https://vm-vcloud/api/admin/group/b8202c48-7151-4e61-9a6c-155474c7d413"
isSync="true"/>
+</QueryResultRecords>
\ No newline at end of file
Added: libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml?rev=1404292&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml (added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml Wed Oct 31
18:47:28 2012
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<QueryResultRecords xmlns="http://www.vmware.com/vcloud/v1.5" total="1" pageSize="30"
page="2" name="user" type="application/vnd.vmware.vcloud.query.records+xml" href="https://vm-vcloud/api/query?type=user&page=2&pageSize=30&format=records&filter=(name==jrambo)"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5
http://66.58.64.27/api/v1.5/schema/master.xsd">
+ <Link rel="alternate" type="application/vnd.vmware.vcloud.query.references+xml" href="https://vm-vcloud/api/query?type=user&page=2&pageSize=30&format=references&filter=(name==jrambo)"/>
+ <Link rel="alternate" type="application/vnd.vmware.vcloud.query.idrecords+xml" href="https://vm-vcloud/api/query?type=user&page=2&pageSize=30&format=idrecords&filter=(name==jrambo)"/>
+ <UserRecord storedVMQuota="0" numberOfStoredVMs="0" numberOfDeployedVMs="0" name="jrambo"
isLdapUser="true" isEnabled="true" fullName="Galet, Michal" deployedVMQuota="0" href="https://vm-vcloud/api/admin/user/a0d29e8e-2b32-4739-ab7d-6a3e795be4db"
storedVMQuotaRank="-1" deployedVMQuotaRank="-1"/>
+</QueryResultRecords>
\ No newline at end of file
Added: libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml?rev=1404292&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml
(added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml
Wed Oct 31 18:47:28 2012
@@ -0,0 +1,10 @@
+<ControlAccessParams xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://22.11.64.27/api/v1.5/schema/master.xsd"
xmlns="http://www.vmware.com/vcloud/v1.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <IsSharedToEveryone>true</IsSharedToEveryone>
+ <EveryoneAccessLevel>ReadOnly</EveryoneAccessLevel>
+ <AccessSettings>
+ <AccessSetting>
+ <Subject type="application/vnd.vmware.admin.group+xml" href="https://vm-vcloud/api/admin/group/b8202c48-7151-4e61-9a6c-155474c7d413"/>
+ <AccessLevel>FullControl</AccessLevel>
+ </AccessSetting>
+ </AccessSettings>
+</ControlAccessParams>
\ No newline at end of file
Modified: libcloud/trunk/libcloud/test/compute/test_vcloud.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/test_vcloud.py?rev=1404292&r1=1404291&r2=1404292&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/test_vcloud.py (original)
+++ libcloud/trunk/libcloud/test/compute/test_vcloud.py Wed Oct 31 18:47:28 2012
@@ -19,8 +19,8 @@ from xml.etree import ElementTree as ET
from libcloud.utils.py3 import httplib, b
-from libcloud.compute.drivers.vcloud import TerremarkDriver, VCloudNodeDriver
-from libcloud.compute.drivers.vcloud import VCloud_1_5_NodeDriver, Vdc
+from libcloud.compute.drivers.vcloud import TerremarkDriver, VCloudNodeDriver, Subject
+from libcloud.compute.drivers.vcloud import VCloud_1_5_NodeDriver, ControlAccess
from libcloud.compute.base import Node, NodeImage
from libcloud.compute.types import NodeState
@@ -139,6 +139,7 @@ class VCloud_1_5_Tests(unittest.TestCase
'state': NodeState.RUNNING,
'public_ips': ['65.41.67.2'],
'private_ips': ['65.41.67.2'],
+ 'os_type': 'rhel5_64Guest'
}]})
node = ret[1]
self.assertEqual(node.id, 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b')
@@ -153,6 +154,7 @@ class VCloud_1_5_Tests(unittest.TestCase
'state': NodeState.RUNNING,
'public_ips': ['192.168.0.103'],
'private_ips': ['192.168.0.100'],
+ 'os_type': 'rhel5_64Guest'
}]})
def test_reboot_node(self):
@@ -243,6 +245,30 @@ class VCloud_1_5_Tests(unittest.TestCase
node = Node('https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b',
'testNode', NodeState.RUNNING, [], [], self.driver)
self.driver.ex_power_off_node(node)
+ def test_ex_query(self):
+ results = self.driver.ex_query('user', filter='name==jrambo', page=2, page_size=30,
sort_desc='startDate')
+ self.assertEqual(len(results), 1)
+ self.assertEqual(results[0]['type'], 'UserRecord')
+ self.assertEqual(results[0]['name'], 'jrambo')
+ self.assertEqual(results[0]['isLdapUser'], 'true')
+
+ def test_ex_get_control_access(self):
+ node = Node('https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b',
'testNode', NodeState.RUNNING, [], [], self.driver)
+ control_access = self.driver.ex_get_control_access(node)
+ self.assertEqual(control_access.everyone_access_level, ControlAccess.AccessLevel.READ_ONLY)
+ self.assertEqual(len(control_access.subjects), 1)
+ self.assertEqual(control_access.subjects[0].type, 'group')
+ self.assertEqual(control_access.subjects[0].name, 'MyGroup')
+ self.assertEqual(control_access.subjects[0].id, 'https://vm-vcloud/api/admin/group/b8202c48-7151-4e61-9a6c-155474c7d413')
+ self.assertEqual(control_access.subjects[0].access_level, ControlAccess.AccessLevel.FULL_CONTROL)
+
+ def test_ex_set_control_access(self):
+ node = Node('https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b',
'testNode', NodeState.RUNNING, [], [], self.driver)
+ control_access = ControlAccess(node, None, [Subject(
+ name = 'MyGroup',
+ type = 'group',
+ access_level = ControlAccess.AccessLevel.FULL_CONTROL)])
+ self.driver.ex_set_control_access(node, control_access)
class TerremarkMockHttp(MockHttp):
@@ -306,13 +332,14 @@ class TerremarkMockHttp(MockHttp):
return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED])
-class VCloud_1_5_MockHttp(MockHttp):
+class VCloud_1_5_MockHttp(MockHttp, unittest.TestCase):
fixtures = ComputeFileFixtures('vcloud_1_5')
def request(self, method, url, body=None, headers=None, raw=False):
- assert url.startswith('/api/'), '"{0}" is invalid. Needs to start with "/api". '
\
- 'The passed URL should be just the path, not full URL.'.format(url)
+ self.assertTrue(url.startswith('/api/'), '"{0}" is invalid. Needs to ' \
+ 'start with "/api". The passed URL should be just ' \
+ 'the path, not full URL.'.format(url))
super(VCloud_1_5_MockHttp, self).request(method, url, body, headers,
raw)
@@ -464,5 +491,36 @@ class VCloud_1_5_MockHttp(MockHttp):
body = self.fixtures.load('api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_all.xml')
return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]
+ def _api_query(self, method, url, body, headers):
+ assert method == 'GET'
+ if 'type=user' in url:
+ self.assertTrue('page=2' in url)
+ self.assertTrue('filter=(name==jrambo)' in url)
+ self.assertTrue('sortDesc=startDate')
+ body = self.fixtures.load('api_query_user.xml')
+ elif 'type=group' in url:
+ body = self.fixtures.load('api_query_group.xml')
+ else:
+ raise AssertionError('Unexpected query type')
+ return httplib.OK, body, headers, httplib.responses[httplib.OK]
+
+ def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_controlAccess(self, method, url,
body, headers):
+ body = self.fixtures.load('api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml')
+ return httplib.OK, body, headers, httplib.responses[httplib.OK]
+
+ def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_action_controlAccess(self, method,
url, body, headers):
+ body = str(body)
+ self.assertTrue(method == 'POST')
+ self.assertTrue('<IsSharedToEveryone>false</IsSharedToEveryone>' in body)
+ self.assertTrue('<Subject href="https://vm-vcloud/api/admin/group/b8202c48-7151-4e61-9a6c-155474c7d413"
/>' in body)
+ self.assertTrue('<AccessLevel>FullControl</AccessLevel>' in body)
+ body = self.fixtures.load('api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml')
+ return httplib.OK, body, headers, httplib.responses[httplib.OK]
+
+ def _api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413(self, method, url, body, headers):
+ body = self.fixtures.load('api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml')
+ return httplib.OK, body, headers, httplib.responses[httplib.OK]
+
+
if __name__ == '__main__':
sys.exit(unittest.main())
|