def _requestComputerPartition(self, request_dict): try: xml = self._connection_helper.POST('/requestComputerPartition', request_dict) except ResourceNotReady: return ComputerPartition( request_dict=request_dict, connection_helper=self._connection_helper, ) software_instance = xml_marshaller.loads(xml) computer_partition = ComputerPartition( software_instance.slap_computer_id.encode('UTF-8'), software_instance.slap_computer_partition_id.encode('UTF-8'), connection_helper=self._connection_helper, ) # Hack to give all object attributes to the ComputerPartition instance # XXX Should be removed by correctly specifying difference between # ComputerPartition and SoftwareInstance computer_partition.__dict__ = dict(computer_partition.__dict__.items() + software_instance.__dict__.items()) # XXX not generic enough. if xml_marshaller.loads(request_dict['shared_xml']): computer_partition._synced = True computer_partition._connection_dict = software_instance._connection_dict computer_partition._parameter_dict = software_instance._parameter_dict return computer_partition
def parseRequestComputerPartitionForm(form): """ Parse without intelligence a form from a request(), return it. """ parsed_dict = {} parsed_dict['software_release'] = form['software_release'].encode() parsed_dict['software_type'] = form.get('software_type').encode() parsed_dict['partition_reference'] = form.get('partition_reference', '').encode() parsed_dict['partition_id'] = form.get('computer_partition_id', '').encode() parsed_dict['partition_parameter_kw'] = loads(form.get('partition_parameter_xml', EMPTY_DICT_XML).encode()) parsed_dict['filter_kw'] = loads(form.get('filter_xml', EMPTY_DICT_XML).encode()) # Note: currently ignored for slave instance (slave instances # are always started). parsed_dict['requested_state'] = loads(form.get('state').encode()) return parsed_dict
def request(self, software_release, partition_reference, partition_parameter_kw=None, software_type=None, filter_kw=None, state=None, shared=False): if partition_parameter_kw is None: partition_parameter_kw = {} if filter_kw is None: filter_kw = {} request_dict = { 'software_release': software_release, 'partition_reference': partition_reference, 'partition_parameter_xml': xml_marshaller.dumps(partition_parameter_kw), 'filter_xml': xml_marshaller.dumps(filter_kw), 'state': xml_marshaller.dumps(state), 'shared_xml': xml_marshaller.dumps(shared), } if software_type is not None: request_dict['software_type'] = software_type try: self._connection_helper.POST('/requestComputerPartition', request_dict) except ResourceNotReady: return ComputerPartition(request_dict=request_dict) else: xml = self._connection_helper.response.read() software_instance = xml_marshaller.loads(xml) return ComputerPartition( software_instance.slap_computer_id.encode('UTF-8'), software_instance.slap_computer_partition_id.encode('UTF-8'))
def getFullHostingIpAddressList(self): xml = self._connection_helper.GET('getHostingSubscriptionIpList', params={ 'computer_id': self._computer_id, 'computer_partition_id': self._partition_id, } ) return xml_marshaller.loads(xml)
def getStatus(self): xml = self._connection_helper.GET('getComputerPartitionStatus', params={ 'computer_id': self._computer_id, 'computer_partition_id': self._partition_id, } ) return xml_marshaller.loads(xml)
def requestComputer(self, computer_reference): """ Requests a computer. """ xml = self._connection_helper.POST('/requestComputer', {'computer_title': computer_reference}) computer = xml_marshaller.loads(xml) computer._connection_helper = self._connection_helper return computer
def requestComputer(self, computer_reference): """ Requests a computer. """ xml = self._connection_helper.POST('requestComputer', data={'computer_title': computer_reference}) computer = xml_marshaller.loads(xml) computer._connection_helper = self._connection_helper computer._hateoas_navigator = self._hateoas_navigator return computer
def registerComputerPartition(self, computer_guid, partition_id): """ Registers connected representation of computer partition and returns Computer Partition class object """ self._connection_helper.GET('/registerComputerPartition?' \ 'computer_reference=%s&computer_partition_reference=%s' % ( computer_guid, partition_id)) xml = self._connection_helper.response.read() return xml_marshaller.loads(xml)
def forwardRequestToExternalMaster(master_url, request_form): """ Forward instance request to external SlapOS Master. """ master_entry = app.config.get('multimaster').get(master_url, {}) key_file = master_entry.get('key') cert_file = master_entry.get('cert') if master_url.startswith('https') and (not key_file or not cert_file): app.logger.warning('External master %s configuration did not specify key or certificate.' % master_url) abort(404) if master_url.startswith('https') and not master_url.startswith('https') and (key_file or cert_file): app.logger.warning('External master %s configurqtion specifies key or certificate but is using plain http.' % master_url) abort(404) slap = slapos.slap.slap() if key_file: slap.initializeConnection(master_url, key_file=key_file, cert_file=cert_file) else: slap.initializeConnection(master_url) partition_reference = request_form['partition_reference'].encode() # Store in database execute_db('forwarded_partition_request', 'INSERT OR REPLACE INTO %s values(:partition_reference, :master_url)', {'partition_reference':partition_reference, 'master_url': master_url}) new_request_form = request_form.copy() filter_kw = loads(new_request_form['filter_xml'].encode()) filter_kw['source_instance_id'] = partition_reference new_request_form['filter_xml'] = dumps(filter_kw) xml = slap._connection_helper.POST('/requestComputerPartition', data=new_request_form) if type(xml) is unicode: xml = str(xml) xml.encode('utf-8') partition = loads(xml) # XXX move to other end partition._master_url = master_url return dumps(partition)
def request(self, software_release, software_type, partition_reference, shared=False, partition_parameter_kw=None, filter_kw=None, state=None): if partition_parameter_kw is None: partition_parameter_kw = {} elif not isinstance(partition_parameter_kw, dict): raise ValueError("Unexpected type of partition_parameter_kw '%s'" % \ partition_parameter_kw) if filter_kw is None: filter_kw = {} elif not isinstance(filter_kw, dict): raise ValueError("Unexpected type of filter_kw '%s'" % \ filter_kw) # Let enforce a default software type if software_type is None: software_type = DEFAULT_SOFTWARE_TYPE request_dict = { 'computer_id': self._computer_id, 'computer_partition_id': self._partition_id, 'software_release': software_release, 'software_type': software_type, 'partition_reference': partition_reference, 'shared_xml': xml_marshaller.dumps(shared), 'partition_parameter_xml': xml_marshaller.dumps( partition_parameter_kw), 'filter_xml': xml_marshaller.dumps(filter_kw), 'state': xml_marshaller.dumps(state), } try: self._connection_helper.POST('/requestComputerPartition', request_dict) except ResourceNotReady: return ComputerPartition( request_dict=request_dict, connection_helper=self._connection_helper, ) else: xml = self._connection_helper.response.read() software_instance = xml_marshaller.loads(xml) computer_partition = ComputerPartition( software_instance.slap_computer_id.encode('UTF-8'), software_instance.slap_computer_partition_id.encode('UTF-8'), connection_helper=self._connection_helper, ) if shared: computer_partition._synced = True computer_partition._connection_dict = getattr(software_instance, '_connection_dict', None) computer_partition._parameter_dict = getattr(software_instance, '_parameter_dict', None) return computer_partition
def load(cls, path_to_xml, reference, ipv6_interface): """ Create a computer object from a valid xml file. Arg: path_to_xml: String, a path to a valid file containing a valid configuration. Return: A Computer object. """ dumped_dict = xml_marshaller.loads(open(path_to_xml).read()) # Reconstructing the computer object from the xml computer = Computer( reference = reference, addr = dumped_dict['address'], netmask = dumped_dict['netmask'], ipv6_interface=ipv6_interface, software_user=dumped_dict.get('software_user', 'slapsoft'), ) for partition_dict in dumped_dict['partition_list']: if partition_dict['user']: user = User(partition_dict['user']['name']) else: user = User('root') if partition_dict['tap']: tap = Tap(partition_dict['tap']['name']) else: tap = Tap(partition_dict['reference']) address_list = partition_dict['address_list'] partition = Partition( reference = partition_dict['reference'], path = partition_dict['path'], user = user, address_list = address_list, tap = tap, ) computer.partition_list.append(partition) return computer
def registerComputerPartition(self, computer_guid, partition_id): """ Registers connected representation of computer partition and returns Computer Partition class object """ if not computer_guid or not partition_id: # XXX-Cedric: should raise something smarter than NotFound raise NotFoundError xml = self._connection_helper.GET('/registerComputerPartition?' \ 'computer_reference=%s&computer_partition_reference=%s' % ( computer_guid, partition_id)) result = xml_marshaller.loads(xml) # XXX: dirty hack to make computer partition usable. xml_marshaller is too # low-level for our needs here. result._connection_helper = self._connection_helper return result
def getFullComputerInformation(self, computer_id): """ Retrieve from SlapOS Master Computer instance containing all needed informations (Software Releases, Computer Partitions, ...). """ method = '/getFullComputerInformation?computer_id=%s' % computer_id if not computer_id: # XXX-Cedric: should raise something smarter than "NotFound". raise NotFoundError(method) try: xml = self.GET(method) except NotFoundError: # XXX: This is a ugly way to keep backward compatibility, # We should stablise slap library soon. xml = self.GET('/getComputerInformation?computer_id=%s' % computer_id) return xml_marshaller.loads(xml)
def request(self, software_release, partition_reference, partition_parameter_kw=None, software_type=None, filter_kw=None, state=None, shared=False): if partition_parameter_kw is None: partition_parameter_kw = {} if filter_kw is None: filter_kw = {} request_dict = { 'software_release': software_release, 'partition_reference': partition_reference, 'partition_parameter_xml': xml_marshaller.dumps(partition_parameter_kw), 'filter_xml': xml_marshaller.dumps(filter_kw), # XXX Cedric: Why state and shared are marshalled? First is a string # And second is a boolean. 'state': xml_marshaller.dumps(state), 'shared_xml': xml_marshaller.dumps(shared), } if software_type is not None: request_dict['software_type'] = software_type else: # Let's enforce a default software type request_dict['software_type'] = DEFAULT_SOFTWARE_TYPE try: self._connection_helper.POST('/requestComputerPartition', request_dict) except ResourceNotReady: return ComputerPartition( request_dict=request_dict, connection_helper=self._connection_helper, ) else: xml = self._connection_helper.response.read() software_instance = xml_marshaller.loads(xml) computer_partition = ComputerPartition( software_instance.slap_computer_id.encode('UTF-8'), software_instance.slap_computer_partition_id.encode('UTF-8'), connection_helper=self._connection_helper, ) if shared: computer_partition._synced = True computer_partition._connection_dict = software_instance._connection_dict computer_partition._parameter_dict = software_instance._parameter_dict return computer_partition
def requestComputerPartition(): parsed_request_dict = parseRequestComputerPartitionForm(request.form) # Is it a slave instance? slave = loads(request.form.get('shared_xml', EMPTY_DICT_XML).encode()) # Check first if instance is already allocated if slave: # XXX: change schema to include a simple "partition_reference" which # is name of the instance. Then, no need to do complex search here. slave_reference = parsed_request_dict['partition_id'] + '_' + parsed_request_dict['partition_reference'] requested_computer_id = parsed_request_dict['filter_kw'].get('computer_guid', app.config['computer_id']) matching_partition = getAllocatedSlaveInstance(slave_reference, requested_computer_id) else: matching_partition = getAllocatedInstance(parsed_request_dict['partition_reference']) if matching_partition: # Then the instance is already allocated, just update it # XXX: split request and request slave into different update/allocate functions and simplify. # By default, ALWAYS request instance on default computer parsed_request_dict['filter_kw'].setdefault('computer_guid', app.config['computer_id']) if slave: software_instance = requestSlave(**parsed_request_dict) else: software_instance = requestNotSlave(**parsed_request_dict) else: # Instance is not yet allocated: try to do it. external_master_url = isRequestToBeForwardedToExternalMaster(parsed_request_dict) if external_master_url: return forwardRequestToExternalMaster(external_master_url, request.form) # XXX add support for automatic deployment on specific node depending on available SR and partitions on each Node. # Note: It only deploys on default node if SLA not specified # XXX: split request and request slave into different update/allocate functions and simplify. # By default, ALWAYS request instance on default computer parsed_request_dict['filter_kw'].setdefault('computer_guid', app.config['computer_id']) if slave: software_instance = requestSlave(**parsed_request_dict) else: software_instance = requestNotSlave(**parsed_request_dict) return dumps(software_instance)
def getFullComputerInformation(self, computer_id): """ Retrieve from SlapOS Master Computer instance containing all needed informations (Software Releases, Computer Partitions, ...). """ path = 'getFullComputerInformation' params = {'computer_id': computer_id} if not computer_id: # XXX-Cedric: should raise something smarter than "NotFound". raise NotFoundError('%r %r' % (path, params)) try: xml = self.GET(path, params=params) except NotFoundError: # XXX: This is a ugly way to keep backward compatibility, # We should stablise slap library soon. xml = self.GET('getComputerInformation', params=params) if type(xml) is unicode: xml = str(xml) xml.encode('utf-8') return xml_marshaller.loads(xml)
def getSoftwareReleaseListFromSoftwareProduct(self, software_product_reference=None, software_release_url=None): url = 'getSoftwareReleaseListFromSoftwareProduct' params = {} if software_product_reference: if software_release_url is not None: raise AttributeError('Both software_product_reference and ' 'software_release_url parameters are specified.') params['software_product_reference'] = software_product_reference else: if software_release_url is None: raise AttributeError('None of software_product_reference and ' 'software_release_url parameters are specified.') params['software_release_url'] = software_release_url xml = self._connection_helper.GET(url, params=params) if type(xml) is unicode: xml = str(xml) xml.encode('utf-8') result = xml_marshaller.loads(xml) assert(type(result) == list) return result
def registerComputerPartition(self, computer_guid, partition_id): """ Registers connected representation of computer partition and returns Computer Partition class object """ if not computer_guid or not partition_id: # XXX-Cedric: should raise something smarter than NotFound raise NotFoundError xml = self._connection_helper.GET('registerComputerPartition', params = { 'computer_reference': computer_guid, 'computer_partition_reference': partition_id, } ) if type(xml) is unicode: xml = str(xml) xml.encode('utf-8') result = xml_marshaller.loads(xml) # XXX: dirty hack to make computer partition usable. xml_marshaller is too # low-level for our needs here. result._connection_helper = self._connection_helper result._hateoas_navigator = self._hateoas_navigator return result
def request(self, software_release, software_type, partition_reference, shared=False, partition_parameter_kw=None, filter_kw=None, state=None): if partition_parameter_kw is None: partition_parameter_kw = {} elif not isinstance(partition_parameter_kw, dict): raise ValueError("Unexpected type of partition_parameter_kw '%s'" % \ partition_parameter_kw) if filter_kw is None: filter_kw = {} elif not isinstance(filter_kw, dict): raise ValueError("Unexpected type of filter_kw '%s'" % \ filter_kw) request_dict = { 'computer_id': self._computer_id, 'computer_partition_id': self._partition_id, 'software_release': software_release, 'software_type': software_type, 'partition_reference': partition_reference, 'shared_xml': xml_marshaller.dumps(shared), 'partition_parameter_xml': xml_marshaller.dumps( partition_parameter_kw), 'filter_xml': xml_marshaller.dumps(filter_kw), 'state': xml_marshaller.dumps(state), } try: self._connection_helper.POST('/requestComputerPartition', request_dict) except ResourceNotReady: return ComputerPartition(request_dict=request_dict) else: xml = self._connection_helper.response.read() software_instance = xml_marshaller.loads(xml) return ComputerPartition( software_instance.slap_computer_id.encode('UTF-8'), software_instance.slap_computer_partition_id.encode('UTF-8'))
def getCertificate(self): self._connection_helper.GET( '/getComputerPartitionCertificate?computer_id=%s&' 'computer_partition_id=%s' % (self._computer_id, self._partition_id)) return xml_marshaller.loads(self._connection_helper.response.read())
def getStatus(self): self._connection_helper.GET( '/getComputerStatus?computer_id=%s' % self._computer_id) return xml_marshaller.loads(self._connection_helper.response.read())
def getComputerInformation(self, computer_id): xml = self.GET('/getComputerInformation?computer_id=%s' % computer_id) return xml_marshaller.loads(xml)
def getStatus(self): xml = self._connection_helper.GET( '/getComputerPartitionStatus?computer_id=%s&' 'computer_partition_id=%s' % (self._computer_id, self._partition_id)) return xml_marshaller.loads(xml)
def generateCertificate(self): xml = self._connection_helper.POST('/generateComputerCertificate', { 'computer_id': self._computer_id}) return xml_marshaller.loads(xml)
def getStatus(self): xml = self._connection_helper.GET( '/getComputerStatus?computer_id=%s' % self._computer_id) return xml_marshaller.loads(xml)
def getComputerInformation(self, computer_id): xml = self.GET('getComputerInformation', params={'computer_id': computer_id}) return xml_marshaller.loads(xml)
def getComputerInformation(self, computer_id): self.GET('/getComputerInformation?computer_id=%s' % computer_id) return xml_marshaller.loads(self.response.read())