Example #1
0
class PublicIP(RestObject):
    def __init__(self, connect, base_resource, uid, initial_data):
        res = "%s/public_ips/%s" % (base_resource, uid)
        super(PublicIP, self).__init__(connect, res, initial_data)

    uid = RestAttribute('id', readonly=True)
    address = RestAttribute('address')
Example #2
0
class Credential(RestObject):
    def __init__(self, connect, res, uid, intial_data):
        super(Credential,
              self).__init__(connect, "%s/credentials/%s" % (res, uid),
                             intial_data)

    uid = RestAttribute("id", readonly=True)
    text = RestAttribute("text")
Example #3
0
class Label(RestObject):
    def __init__(self, connect, res, uid, intial_data):
        super(Label, self).__init__(connect, "%s/labels/%s" % (res, uid),
                                    intial_data)

    uid = RestAttribute("id", readonly=True)
    text = RestAttribute("text")
    label_type = RestAttribute("type")
Example #4
0
class PublishedService(RestObject):
    def __init__(self, connect, base_resource, uid, initial_data):
        res = "%s/services/%s" % (base_resource, uid)
        super(PublishedService, self).__init__(connect, res, initial_data)

    uid = RestAttribute('id', readonly=True)
    external_port = RestAttribute('external_port', readonly=True)
    internal_port = RestAttribute('internal_port')
    external_ip = RestAttribute('external_ip', readonly=True)
Example #5
0
class Hardware(RestObject):
    def __init__(self, connect, res, initial_data, parent):
        super(Hardware, self).__init__(connect,
                                       res,
                                       initial_data,
                                       is_full=True,
                                       parent=parent,
                                       parent_attr="hardware")

    cpus = RestAttribute("cpus")
    guest_os = RestAttribute("guestOS", readonly=True)
    max_cpus = RestAttribute("max_cpus", readonly=True)
    max_ram = RestAttribute("max_ram", readonly=True)
    min_ram = RestAttribute("min_ram", readonly=True)
    ram = RestAttribute("ram")
    svms = RestAttribute("svms", readonly=True)
    upgradable = RestAttribute("upgradable", readonly=True)
    vnc_keymap = RestAttribute("vnc_keymap", readonly=True)

    def disks(self):
        return [
            Disk(self._connect, self._resource, disk)
            for disk in self.alldata()['disks']
        ]

    def addDisk(self, size):
        msg = {"hardware": {"disks": {"new": [size]}}}
        self._connect.put(self._resource, body=msg)
Example #6
0
class Note(RestObject):
    def __init__(self, connect, res, uid, intial_data):
        super(Note, self).__init__(connect,
                                   "%s/notes/%s" % (res, uid),
                                   intial_data,
                                   can_refresh=False)

    uid = RestAttribute("id", readonly=True)
    text = RestAttribute("text")
    time = RestAttribute("time", readonly=True)
    user_id = RestAttribute("user_id", readonly=True)
Example #7
0
class Template(AssignableObject):
    """
    A template is a specification of one or more virtual machine images,
    plus associated resources such as network configurations, as well as
    metadata such as notes and tags.

    The purpose of a template is to serve as a blueprint from which any
    number of runnable configurations can be created. As such, a template
    is not directly runnable, and there are constraints on the ways a
    template can be modified once created. Many of the template attributes
    in the API are only informative, and cannot be modified unless working
    on an equivalent configuration. For example, the "runstate" attribute
    will list the state of the VMs in this template, but cannot be changed
    in the API.
    """
    
    def __init__(self, connect, uid, intial_data, configuration_cls, user_cls):
        super(Template, self).__init__(connect, "templates/%s" % (uid),
            intial_data, "templates", user_cls)
        self._configuration_cls = configuration_cls
        
    uid = RestAttribute('id', readonly=True)
    name = RestAttribute('name')
    url = RestAttribute('url', readonly=True)
    busy = RestAttribute('busy', readonly=True)
    description = RestAttribute('description')
    lockversion = RestAttribute('lockversion', readonly=True)
    public = RestAttribute('public')
    tagList = RestAttribute('tag_list')
    region = RestAttribute('region', readonly=True)
                    
    def vms(self):
        return VirtualMachines(self._connect, self._resource)
            
    def networks(self):
        return VirtualNetworks(self._connect, self._resource)
    
    def create_configuration(self, vm_ids=None):
        body = {'template_id':self.uid}
        if vm_ids is not None:
            body['vm_ids'] = vm_ids
        result = self._connect.post("configurations", body=body)
        return self._configuration_cls(self._connect, result['id'],
            result, Template, self._user_cls)

    def wait_for(self, check_interval=15, check_limit=20):
        remaining = check_limit
        busy = True
        while busy and remaining > 0:
            remaining -= 1
            self.refresh()
            busy = self.busy
            if busy:
                time.sleep(check_interval)
        if busy:
            raise SkytapException("Failed to wait for state change on "
                "template %s" % self.uid)
Example #8
0
class CompanyResourceLimit(RestObject):
    def __init__(self, connect, res, parent, attrname):
        super(CompanyResourceLimit,
              self).__init__(connect,
                             res,
                             parent.alldata().get(attrname),
                             is_full=True,
                             parent=parent,
                             parent_attr=attrname)

    quota_type = RestAttribute('quota_type', readonly=True)
    units = RestAttribute('units', readonly=True)
    limit = RestAttribute('limit', readonly=True)
    usage = RestAttribute('subscription', readonly=True)
    max_limit = RestAttribute('max_limit', readonly=True)
Example #9
0
class AssignableObject(RestObject):
    """
    Assignable Object is a base class for Skytap objects like Configuration and
    Template that can assigned or re-assigned an owner. Assignable Objects can
    also manage access by adding itself to Skytap projects.

    Attributes:
       none
    """
    def __init__(self, connect, resource, initial_data, obj_type, user_cls):
        """
        Constructor for a Assignable object.
    
        Parameters
            connect - the Connect object that managed REST requests to skytap
            resource- the path to skytap resource for this Assignable object
            initialData - a partial dictionary of properties for the Assignable
                object. This partial data is obtained from the parent list
                when the library queries skytap for a list of objects.
        """
        super(AssignableObject, self).__init__(connect, resource, initial_data)
        self._obj_type = obj_type
        self._user_cls = user_cls

    owner_url = RestAttribute('owner')

    def owner(self):
        if self.owner_url is None:
            return None
        (_, _, path, _, _) = urlparse.urlsplit(self.owner_url)
        owner_id = path.split('/')[-1]
        return self._user_cls(self._connect, owner_id, {})

    def reassign(self, user, project=None):
        """
        Reassign the user that owns this skytap resource.
        Parameters
            user - The skytap object for the user. Lookup the user in the
                   skytap.users() dictionary.
            project - Reassigning the owner will clear the projects this
                   resource belongs to. You have to option of passing a
                   single project that the resource will be added to.
        """
        body = {'owner': user.uid}
        if (project is not None):
            body['reassign_context'] = project.uid
        self.data = self._connect.put(self._resource, body=body)

    def add_to_project(self, project, role=None):
        """
        Add this resource to a Skytap project.
        Parameters
            project - The project object can be found in the skytap.projects()
                      dictionary.
            role - Optional parameter used when adding user or group object to
                   a project. Valid values are 'viewer', 'participant', 
                   'editor' or 'manager'.
        """
        project.add(self, self._obj_type, role)
Example #10
0
class StatefulObject(RestObject):

    runstate = RestAttribute('runstate')

    def check_state(self, states=None):
        if states is None:
            return self.runstate != 'busy'
        else:
            return self.runstate in states
Example #11
0
class VirtualNetwork(RestObject):
    def __init__(self, connect, base_resource, uid, intial_data):
        res = "%s/networks/%s" % (base_resource, uid)
        super(VirtualNetwork, self).__init__(connect, res, intial_data)

    uid = RestAttribute('id', readonly=True)
    name = RestAttribute('name')
    domain = RestAttribute('domain')
    gateway = RestAttribute('gateway')
    network_type = RestAttribute('network_type')
    primary_nameserver = RestAttribute('primary_nameserver')
    secondary_nameserver = RestAttribute('secondary_nameserver')
    subnet = RestAttribute('subnet', readonly=True)
    subnet_addr = RestAttribute('subnet_addr')
    subnet_size = RestAttribute('subnet_size')
    tunnelable = RestBoolAttribute('tunnelable')

    def tunnels(self):
        return [
            Tunnel(self._connect, tunnel['id'], tunnel)
            for tunnel in self.alldata()['tunnels']
        ]

    def create_tunnel(self, target_network):
        args = {
            'source_network_id': str(self.uid),
            'target_network_id': str(target_network)
        }
        result = self._connect.post("tunnels", args)
        return Tunnel(self._connect, result['id'], result)

    def attach_vpn(self, vpn):
        body = {'vpn_id': vpn.uid}
        result = self._connect.post("%s/vpns" % self._resource, body)
        return AttachedVPN(self._connect, self._resource, vpn.uid, result)

    def vpns(self):
        return [
            AttachedVPN(self._connect, self._resource, att['vpn']['id'], att)
            for att in self.alldata()['vpn_attachments']
        ]
Example #12
0
class PublishSetVM(RestObject):
    def __init__(self, connect, res, initial_data, vm_cls):
        super(PublishSetVM, self).__init__(connect,
                                           res,
                                           initial_data,
                                           can_delete=True,
                                           is_full=True,
                                           can_refresh=False)
        self._vm_cls = vm_cls

    uid = RestAttribute("id", readonly=True)
    name = RestAttribute("name")
    access = RestAttribute("access")
    desktop_url = RestAttribute("desktop_url")
    run_and_use = RestAttribute("run_and_use")

    def virtual_machine(self):
        items = self.alldata()['vm_ref'].split("/")
        res = '/'.join(items[3:-2])
        uid = items[-1]
        return self._vm_cls(self._connect, res, uid, {'id': uid})
Example #13
0
class Disk(RestObject):
    def __init__(self, connect, res, initial_data):
        super(Disk, self).__init__(connect,
                                   res,
                                   initial_data,
                                   is_full=True,
                                   can_refresh=False)

    controller = RestAttribute('controller', readonly=True)
    uid = RestAttribute('id', readonly=True)
    lun = RestAttribute('lun', readonly=True)
    size = RestAttribute('size', readonly=True)
    disk_type = RestAttribute('type', readonly=True)

    def delete(self):
        msg = {'hardware': {'disks': {'existing': {}}}}
        msg['hardware']['disks']['existing'][self.uid] = {
            'id': self.uid,
            'size': None
        }
        self._connect.put(self._resource, body=msg)
        self._active = False
Example #14
0
class AttachedVPN(RestObject):
    """
    This object represents the relationship between a Virtual Network
    and a VPN. A Virtual Network can be attached to multiple VPNs, and
    a VPN can have multiple Virtual Networks. This object represent a
    single pair of a an Attached Virtual Network, and the VPN it is 
    attached to.
    """ 
    
    def __init__(self, connect, base_resource, vpn_id, intial_data):
        res = "%s/vpns/%s" % (base_resource, vpn_id)
        super(AttachedVPN, self).__init__(connect, res, intial_data,
            is_full=True)

    uid = RestAttribute('id', readonly=True)
    connected = RestBoolAttribute('connected')

    def network_id(self):
        """
        Return the skytap id for the Virtual Network attached to the
        VPN.
        """
        return self.alldata()['network']['id']

    def configuration_id(self):
        """
        Every virtual network belongs to a Skytap configuration. This
        method returns the id of the configuration that the attached
        virtual network belongs to.
        """
        return self.alldata()['network']['configuration_id']

    def vpn_id(self):
        """
        Return the id for the attached VPN.
        """
        return self.alldata()['vpn']['id']

    def vpn(self):
        """
        Return the VPN object the virtual network is attached to.
        """
        data = self.alldata()['vpn']
        return VPN(self._connect, self.vpn_id(), data)

    def detach(self):
        """
        Detach the virtual network from the VPN. This method is
        equivalent to calling delete() on this object.
        """
        return self.delete()
Example #15
0
class Asset(AssignableObject):
    """
    Generally, a customer asset is any data available in the Skytap
    Cloud context. Typically this is data that a customer has loaded
    into Skytap Cloud to support running applications.
    Assets are top-level elements in the API data model.
    In the current release of the API, Assets can only be viewed, 
    referenced and ownership managed, but not created, modified,
    or deleted.
    
    Attributes
        uid - unique identifier for asset object.
        name - human friendly name for the asset.
        public - True or false this asset is with other users in skytap.
        size - the size of the asset file.
        url - a url that can used to download a copy of the asset.
    """
    def __init__(self, connect, uid, initial_data, user_cls):
        '''
        Constructor
        
        Create a new Asset object
        
        Parameters
            connect - A connect.Connect object used to communicate with the
                Skytap REST API.
            uid - The unique identifier for the Asset object.
            initialData  - A dict containing a partial cache of the name/value 
                attributes for this asset.
        '''
        super(Asset, self).__init__(connect, "assets/%s" % (uid), initial_data,
                                    "assets", user_cls)

    uid = RestAttribute("id", readonly=True)
    name = RestAttribute("name", readonly=True)
    public = RestAttribute("public", readonly=True)
    size = RestAttribute("size", readonly=True)
    url = RestAttribute("url", readonly=True)
Example #16
0
class UsageReport(RestObject):
    def __init__(self, connect, uid, initial_data):
        '''
        Constructor
        
        Create a new Usage Report
        
        Parameters
            connect - A connect.Connect object used to communicate with the
                Skytap REST API.
            uid - The unique identifier for the Usage Report object.
            initialData  - A dict containing a partial cache of the name/value 
                attributes for this usage report.
        '''
        super(UsageReport, self).__init__(connect, "reports/%s" % uid,
                                          initial_data)

    uid = RestAttribute("id", readonly=True)
    start_date = RestAttribute("start_date")
    end_date = RestAttribute("end_date")
    utc = RestBoolAttribute("utc")
    resource_type = RestAttribute("resource_type")
    region = RestAttribute("region")
    ready = RestBoolAttribute("ready", readonly=True)
    url = RestAttribute("url", readonly=True)

    def wait_for(self, check_interval=10, check_limit=10):
        """
        Blocking call to wait for the usage report to be
        ready. Once the report is ready (finished generating),
        the get_reader() method can be used to read the data
        for the report.
        """
        remaining = check_limit
        ready = False
        while not ready and remaining > 0:
            remaining -= 1
            self.refresh()
            ready = self.ready
            if not ready:
                time.sleep(check_interval)
        if not ready:
            raise SkytapException("Timeout waiting for report %s"
                                  "to be ready." % self.uid)

    def get_reader(self):
        """
        Returns a reader for the usage report data. The returned
        object is a csv.DictReader. Use method next() on DictReader
        to read each row of the report. Each row is a python dict
        with column names as key, and the values of the current row.
        """
        contents = self._connect.request(self.url,
                                         'GET',
                                         accept_type='application/csv')
        clean_data = contents.encode('ascii', 'ignore')
        return csv.DictReader(clean_data.split('\n'))
Example #17
0
class Tunnel(RestObject):
    """
    A network tunnel created by connecting two virtual skytap networks
    together. Note: the networks must use non-overlaping subnets.
    """
    def __init__(self, connect, uid, initial_data):
        super(Tunnel, self).__init__(connect, "tunnels/%s" % (uid),
                                     initial_data)

    uid = RestAttribute("id", readonly=True)
    status = RestAttribute("status", readonly=True)

    def source_network(self):
        """
        Returns the network id for the source network in the tunnel.
        """
        return self.alldata()["source_network"]["id"]

    def target_network(self):
        """
        Returns the network id for the target network in the tunnel.
        """
        return self.alldata()["target_network"]["id"]

    def check_state(self, states=None):
        """
        Return a boolean value yes or no. The tunnel is in one of the 
        states passed in states argument. If states is None, then check
        for any state except 'busy'.
        """
        if states is None:
            return self.status != 'busy'
        elif self.status in states:
            return True
        else:
            return False
Example #18
0
class PublishSet(RestObject):
    def __init__(self, connect, res, uid, intial_data, vm_cls):
        super(PublishSet,
              self).__init__(connect, "%s/publish_sets/%s" % (res, uid),
                             intial_data)
        self._vm_cls = vm_cls

    uid = RestAttribute("id", readonly=True)
    name = RestAttribute("name")
    password = RestAttribute("password")
    publish_set_type = RestAttribute("publish_set_type")
    start_time = RestAttribute("start_time")
    end_time = RestAttribute("end_time")
    time_zone = RestAttribute("time_zone")
    url = RestAttribute("url", readonly=True)
    useSmartClient = RestAttribute("use_smart_client", readonly=True)

    def published_vms(self):
        return [
            PublishSetVM(self._connect, self._resource, item, self._vm_cls)
            for item in self.alldata()['vms']
        ]
Example #19
0
class VirtualMachine(StatefulObject):
    def __init__(self, connect, base_resource, uid, initial_data):
        res = "%s/vms/%s" % (base_resource, uid)
        super(VirtualMachine, self).__init__(connect, res, initial_data)

    uid = RestAttribute('id', readonly=True)
    name = RestAttribute('name')
    assetId = RestAttribute('asset_id')
    can_change_object_state = RestAttribute('can_change_object_state')
    desktop_resizable = RestAttribute('desktop_resizable')
    error = RestAttribute('error', readonly=True)
    local_mouse_cursor = RestAttribute('local_mouse_cursor')

    def credentials(self):
        return Credentials(self._connect, self._resource)

    def notes(self):
        return Notes(self._connect, self._resource)

    def labels(self):
        return Labels(self._connect, self._resource, "VmInstance")

    def interfaces(self):
        return Interfaces(self._connect, self._resource)

    def mount_iso(self, asset_id):
        self._connect.put(self._resource, args={'asset_id': asset_id})

    def hardware(self):
        return Hardware(self._connect, self._resource, self.data['hardware'],
                        self)

    @classmethod
    def _extract_path(cls, resource_paths):
        for path in resource_paths:
            items = path.split("/")
            yield ('/'.join(items[3:-2]), items[-1])

    def publish_sets(self):
        publish_set_data = self.alldata().get('publish_set_refs') or []
        path_tuples = self._extract_path(publish_set_data)
        return [
            PublishSet(self._connect, pset[0], pset[1], {}, VirtualMachine)
            for pset in path_tuples
        ]
Example #20
0
class User(RestObject):
    def __init__(self, connect, uid, intial_data):
        super(User, self).__init__(connect, "users/%s" % (uid), intial_data)

    email = RestAttribute("email")
    first_name = RestAttribute("first_name")
    uid = RestAttribute("id", readonly=True)
    last_name = RestAttribute("last_name")
    login_name = RestAttribute("login_name")
    title = RestAttribute("title")
    account_role = RestAttribute("account_role")
    activated = RestAttribute("activated")
    can_export = RestAttribute("can_export")
    can_import = RestAttribute("can_import")
    sra_compression = RestAttribute("sra_compression")
    lockversion = RestAttribute("lockversion", readonly=True)
    password = RestAttribute("password")
Example #21
0
class VPN(RestObject):
    def __init__(self, connect, uid, intial_data):
        super(VPN, self).__init__(connect, "vpns/%s" % (uid), intial_data)
    
    dpd_enabled = RestAttribute('dpd_enabled')
    enabled = RestAttribute('enabled')
    error = RestAttribute('error', readonly=True)
    uid = RestAttribute('id', readonly=True)
    local_peer_ip = RestAttribute('local_peer_ip')
    local_subnet = RestAttribute('local_subnet')
    maximum_segment_size = RestAttribute('maximum_segment_size')
    phase_1_dh_group = RestAttribute('phase_1_dh_group')
    phase_1_encryption_algorithm = RestAttribute('phase_1_encryption_algorithm')
    phase_1_hash_algorithm = RestAttribute('phase_1_hash_algorithm')
    phase_1_sa_lifetime = RestAttribute('phase_1_sa_lifetime')
    # pylint: disable=C0103
    phase_2_authenticatioDn_algorithm = RestAttribute(
        'phase_2_authentication_algorithm')
    phase_2_encryption_algorithm = RestAttribute('phase_2_encryption_algorithm')
    phase_2_perfect_forward_secrecy = RestAttribute(
        'phase_2_perfect_forward_secrecy')
    # pylint: enable=C0103
    phase_2_pfs_group = RestAttribute('phase_2_pfs_group')
    phase_2_sa_lifetime = RestAttribute('phase_2_sa_lifetime')
    remote_peer_ip = RestAttribute('remote_peer_ip')
    status = RestAttribute('status')
    region = RestAttribute('region', readonly=True)

    #u'remote_subnets': [   {   u'cidr_block': u'10.1.0.0/23',
    #                           u'excluded': False,
    #                           u'id': u'10.1.0.0/23'}]
    #u'test_results': {   u'connect': False,
    #                     u'phase1': True,
    #                     u'phase2': True,
    #                     u'ping': False}}
    #u'network_attachments': [   {   u'configuration_id': u'536580',
    #                              u'configuration_name': u'rwh-singleNode',
    #                              u'configuration_type': u'configuration',
    #                              u'connected': True,
    #                              u'network_id': u'339508',
    #                              u'network_name': u'Network 1',
    #                              u'owner_id': u'22638',
    #                              u'owner_name': u'Bill Mepham (bmepham)',
    #                              u'subnet': u'192.168.0.0/24'} ]

    def list_allocations(self, min_net_class=24):
        vpn = self.alldata()
        total = vpn['local_subnet'].split("/")
        alloc = []
        for net in vpn['network_attachments']:
            subnet = net['network']['subnet'].split("/")
            ip_num = VPN.ip_to_number(subnet[0])
            alloc.append((net['network']['configuration_id'], ip_num,
                int(subnet[1]), subnet[0]))
        alloc.sort(key=lambda tup: tup[1])
        start = VPN.ip_to_number(total[0])
        end = start + math.pow(2, 32 - int(total[1]))
        index = start
            
        subnets = []
        for cur in alloc:
            if(index < cur[1]):
                VPN.unallocated(index, cur[1], min_net_class, subnets)
            network = { "configuration_id": cur[0],
                        "subnet": "%s/%d" % (cur[3], cur[2]) }
            subnets.append(network)
            index = cur[1] + math.pow(2, 32 - int(cur[2]))
        if(index < end):
            VPN.unallocated(index, end, min_net_class, subnets)
        return subnets
    
    @staticmethod          
    def unallocated(start, end, min_net_class, results):
        if(start < end):
            inc = min(32 - min_net_class, math.floor(math.log(end - start, 2)))
            power = math.pow(2, inc)
            rem = start % power
            if(rem != 0):
                VPN.unallocated(start, start + rem, min_net_class, results)
                VPN.unallocated(start + rem, end, min_net_class, results)
            else:
                rec = { "configuration_id": "UNALLOCATED",
                        "subnet": "%s/%d" % (VPN.number_to_ip(start),
                             32 - inc) }
                results.append(rec)
                if(inc != 0 and start + power < end):
                    VPN.unallocated(start + power, end, min_net_class, results)
    
    @staticmethod    
    def ip_to_number(ip_addr):
        "convert decimal dotted quad string to long integer"

        hexn = ''.join(["%02X" % long(seg) for seg in ip_addr.split('.')])
        return long(hexn, 16)
    
    @staticmethod
    def number_to_ip(val):
        "convert long int to dotted quad string"
        denom = 256 * 256 * 256
        quad = []
        while denom > 0:
            seg, val = divmod(val, denom)
            quad.append(str(int(seg)))
            denom = denom / 256
        return '.'.join(quad)
Example #22
0
class Interface(RestObject):
    def __init__(self, connect, base_resource, uid, intial_data):
        res = "%s/interfaces/%s" % (base_resource, uid)
        super(Interface, self).__init__(connect, res, intial_data)
    
    uid = RestAttribute("id", readonly=True)
    hostname = RestAttribute("hostname")
    # pylint: disable=C0103
    ip = RestAttribute("ip")
    # pylint: enable=C0103
    mac = RestAttribute("mac")
    network_id = RestAttribute("network_id", readonly=True)
    network_name = RestAttribute("network_name", readonly=True)
    network_subnet = RestAttribute("network_subnet", readonly=True)
    network_type = RestAttribute("network_type", readonly=True)
    nic_type = RestAttribute("nic_type")
    status = RestAttribute("status", readonly=True)
    vm_id = RestAttribute("vm_id", readonly=True)
    vm_name = RestAttribute("vm_name", readonly=True)
    public_ips_count = RestAttribute("public_ips_count", readonly=True)
    services_count = RestAttribute("services_count", readonly=True)
    
    # FIX PUBLIC IPs TO INCLUDE ADD and DELETE
    def public_ips(self):
        return [ips['address'] for ips in self.alldata()['public_ips']]
    
    def services(self):
        return PublishedServices(self._connect, self._resource)
Example #23
0
class Configuration(AssignableObject, StatefulObject):
    """
    Like a template, a configuration is a specification that describes one or more
    virtual machine images, associated resources, and metadata around ownership,
    composition and resources. Unlike a template, many more of the properties of a
    configuration may be modified. More importantly, a configuration can be run.
    
    Attributes:
        runstate
        uid
        name
        url
        disable_internet
        error
        lockversion
        routable
        suspendOnIdle
        useSmartClient
    """

    def __init__(self, connect, uid, initial_data, template_cls, user_cls):
        """
        Constructor for a Configuration object.
    
        Parameters
            connect - the Connect object that managed REST requests to skytap
            uid - the skytap unique identifier for the Configuration object
            initialData - a partial dictionary of properties for the Configuration.
                This partial data is obtained from the Configurations object when
                it queries skytap for a list of configurations.
            templateCls - This parameter a reference to the dxskytap.Template
                class. It is required as a parameter to solve a dependency
                problem, which is explained here.
        """
        super(Configuration, self).__init__(connect,
            "configurations/%s" % (uid),
            initial_data, "configurations", user_cls)
        self._template_cls = template_cls
        
    uid = RestAttribute('id', readonly=True)
    name = RestAttribute('name')
    url = RestAttribute('url', readonly=True)
    disable_internet = RestAttribute('disable_internet')
    error = RestAttribute('error', readonly=True)
    lockversion = RestAttribute('lockversion', readonly=True)
    routable = RestAttribute('routable')
    suspendOnIdle = RestAttribute('suspend_on_idle')
    useSmartClient = RestAttribute('use_smart_client')
    region = RestAttribute('region', readonly=True)
    
    def publish_sets(self):
        return PublishSets(self._connect, self._resource, VirtualMachine)
    
    def vms(self):
        return VirtualMachines(self._connect, self._resource)
    
    def networks(self):
        return VirtualNetworks(self._connect, self._resource)
    
    def notes(self):
        return Notes(self._connect, self._resource)
    
    def labels(self):
        return Labels(self._connect, self._resource, "ConfigurationTemplate")
    
    def merge_template(self, template_id, vm_ids=None):
        body = {'template_id':template_id}
        if(vm_ids is not None):
            body['vm_ids'] = vm_ids 
        return self._connect.put(self._resource, body=body)

    def create_template(self, vm_ids=None):
        body = {'configuration_id':self.uid}
        if(vm_ids is not None):
            body['vm_ids'] = vm_ids
        result = self._connect.post("templates", body=body)
        return self._template_cls(self._connect, result['id'], result,
            Configuration, self._user_cls)

    def wait_for(self, states=None, check_interval=15, check_limit=20):
        resources = [self]
        resources.extend(self.vms().values())
        for network in self.networks().values():
            resources.extend(network.tunnels())
        # TODO: add VPN to resource list
        remaining = check_limit
        ready = False
        while not ready and remaining > 0:
            remaining -= 1
            ready = True
            for res in resources:
                try:
                    res.refresh()
                except ValueError:
                    pass
                ready &= res.check_state(states)
            if not ready:
                time.sleep(check_interval)
        if not ready:
            raise SkytapException("Failed to wait for state change on "
                "configuration %s" % self.uid)
Example #24
0
class Project(RestObject):
    """
    A project is a simple object in skytap used to share resources
    (configurations, templates and assets) between users. Add 
    resources to projects and assign users roles as part of a project.

    Attributes:
        uid
        name
        summary
        show-project-members
        auto-add-role-name
    """
    def __init__(self, connect, uid, initial_data):
        """
        Constructor for a Project object.
    
        Parameters
            connect - the Connect object that managed REST requests to skytap
            uid - the skytap unique identifier for the Configuration object
            initialData - a partial dictionary of properties for the Project.
                This partial data is obtained from the Projects object when
                it queries skytap for a list of projects.
        """
        super(Project, self).__init__(connect, "projects/%s" % (uid),
                                      initial_data)

    uid = RestAttribute('id', readonly=True)
    name = RestAttribute('name')
    summary = RestAttribute('summary')
    showProjectMembers = RestBoolAttribute('show-project-members')
    autoAddRoleName = RestAttribute('auto-add-role-name')

    def templates(self):
        """
        Returns a list of all Skytap templates that are part of this
        project.
        """
        results = self._connect.get("templates")
        return [
            Template(self._connect, data['id'], data, Configuration, User)
            for data in results
        ]

    def configurations(self):
        """
        Returns a list of all Skytap configurations that are part of this
        project.
        """
        results = self._connect.get("configurations")
        return [
            Configuration(self._connect, data['id'], data, Template, User)
            for data in results
        ]

    def add(self, obj, obj_type, role=None):
        """
        :obj: Skytap Resource to be added to the project
        :obj_type: configurations, templates, assets, group, or users
        :role: viewer, participant, editor or manager
        """
        args = {}
        if role is not None:
            args['role'] = str(role)
        self._connect.post("%s/%s/%s" % (self._resource, obj_type, obj.uid),
                           args=args)