class IncomingMachineRequest(ReadonlyContainer): implements(IIncomingMachineRequest) permissions(dict(hostname='read')) def __init__(self, hostname): self.__name__ = hostname self.hostname = hostname
class OpenVZContainer(ReadonlyContainer): permissions(dict(backend=('read', 'modify'))) __name__ = 'openvz' __contains__ = IVirtualCompute @property def _items(self): # break an import cycle from opennode.oms.zodb import db machines = db.get_root()['oms_root']['machines'] computes = {} def collect(container): from opennode.knot.model.machines import Machines seen = set() for item in container.listcontent(): if ICompute.providedBy(item) and item.ctid is not None: computes[str(item.ctid)] = Symlink(str(item.ctid), item) if (isinstance(item, Machines) or isinstance(item, Computes) or ICompute.providedBy(item) or IVirtualizationContainer.providedBy(item)): if item.__name__ not in seen: seen.add(item.__name__) collect(item) collect(machines) return computes
class VncConsole(ReadonlyContainer): implements(IVncConsole, IGraphicalConsole) permissions(dict(hostname=('read', 'modify'), port=('read', 'modify'), )) proxy_processes = {} def __init__(self, hostname, port): self.inherit_permissions = True self.__name__ = 'vnc' self.hostname = hostname self.port = port self._ensure_proxy() def _ensure_proxy(self): if self.hostname in self.proxy_processes: # check if the proxy process has matching vnc port # otherwise kills it if self.proxy_processes[self.hostname].port != self.port: self.proxy_processes[self.hostname].kill() del self.proxy_processes[self.hostname] if self.hostname not in self.proxy_processes: self.proxy_processes[self.hostname] = VncProxyProcess(self.hostname, self.port) @property def ws_url(self): self._ensure_proxy() proxy_port = self.proxy_processes[self.hostname].proxy_port return 'ws://%s:%s/' % (self.hostname, proxy_port)
class OpenVzConsole(ReadonlyContainer): implements(IOpenVzConsole, ITextualConsole) permissions(dict(cid=('read', 'modify'))) def __init__(self, name, cid): self.inherit_permissions = True self.__name__ = name self.cid = cid
class TtyConsole(ReadonlyContainer): implements(ITtyConsole, ITextualConsole) permissions(dict(pty=('read', 'modify'))) def __init__(self, name, pty): self.inherit_permissions = True self.__name__ = name self.pty = pty
class SshConsole(ReadonlyContainer): implements(ISshConsole, ITextualConsole) permissions(dict(user=('read', 'modify'), hostname=('read', 'modify'), port=('read', 'modify'), )) def __init__(self, name, user, hostname, port): self.inherit_permissions = True self.__name__ = name self.user = user self.hostname = hostname self.port = port
class VirtualizationContainer(Container): implements(IVirtualizationContainer, IInCompute, IInHangar) permissions(dict(backend=('read', 'modify'))) __contains__ = IVirtualCompute def __init__(self, backend): super(VirtualizationContainer, self).__init__() self.backend = backend self.__name__ = 'vms-%s' % backend def __str__(self): return 'virtualizationcontainer-%s' % self.__name__ def __repr__(self): return '<VirtualizationContainer backend=%s parent=%s id=0x%X>' % ( self.__name__, self.__parent__, id(self))
class Compute(Container): """A compute node.""" implements(ICompute, IDisplayName) permissions(dict(architecture='read', state='modify')) __contains__ = IInCompute _ipv4_address = u'0.0.0.0/32' ipv6_address = u'::/128' nameservers = [] dns_domains = [] type = 'unknown' # XXX: how should this be determined? # and how do we differentiate for ONC physical and virtual computes? architecture = (u'x86_64', u'linux', u'centos') cpu_info = u"Intel Xeon 12.2GHz" disk_info = u"Seagate Barracuda SuperSaver 2000TB BuyNow!" memory_info = u"1333MHz DDR SuperGoodMemory!" os_release = u"build 35" kernel = u"2.6.18-238.9.1.el5.028stab089.1" num_cores = 1 memory = 2048, network = 12.5 * M # bytes diskspace = { u'total': 2000.0, u'root': 500.0, u'boot': 100.0, u'storage': 1000.0, } swap_size = 4192 cpu_usage = (0.1, 0.11, 0.14) memory_usage = 773.2 network_usage = (5.2 * M, 1.9 * M) diskspace_usage = { u'root': 249.0, u'boot': 49.3, u'storage': 748.3, } cpu_limit = 1.0 autostart = False startup_timestamp = "2011-07-06 01:23:45" def __init__(self, hostname, state, memory=None, template=None, ipv4_address=None): super(Compute, self).__init__() self.hostname = hostname self.memory = memory self.state = state self.template = template if ipv4_address: self._ipv4_address = ipv4_address #if self.template: # alsoProvides(self, IVirtualCompute) #else: # alsoProvides(self, IFuncInstalled) alsoProvides(self, IIncomplete) alsoProvides(self, IUndeployed) assert self.hostname def display_name(self): return self.hostname.encode('utf-8') @property def nicknames(self): """Returns all the nicknames of this Compute instance. Nicknames can be used to traverse to this object using alternative, potentially more convenient and/more memorable, names. """ return [ self.hostname, ] def get_effective_state(self): """Since we lack schema/data upgrade scripts I have to resort on this tricks to cope with the fact that I have existing objects around in the several test dbs, and branches. """ return getattr(self, '_effective_state', unicode(self.state)) def set_effective_state(self, value): self._effective_state = value effective_state = property(get_effective_state, set_effective_state) def __str__(self): return 'compute%s' % self.__name__ def get_consoles(self): return None def set_consoles(self, value): pass consoles = property(get_consoles, set_consoles) @property def templates(self): return None def get_interfaces(self): return None def set_interfaces(self, value): pass interfaces = property(get_interfaces, set_interfaces) def get_routes(self): return None def set_routes(self, value): pass routes = property(get_routes, set_routes) @property def ipv4_address(self): if 'interfaces' not in self._items: return self._ipv4_address addresses = [ i.ipv4_address for i in self._items['interfaces'] if i.ipv4_address ] if not addresses: return self._ipv4_address return unicode(addresses[0])
class UserProfile(Model): implements(IUserProfile, IDisplayName, IMarkable) permissions({ 'name': ('read', 'modify'), 'groups': ('read', 'modify'), 'credit': ('read', 'modify'), 'balance_limit': ('read', 'modify'), 'credit_timestamp': 'read', 'uid': ('read', 'modify'), 'vm_stats': ('read', 'modify'), 'vm_stats_timestamp': 'read' }) __name__ = None groups = [] _credit = 0 _balance_limit = 0 _credit_timestamp = None _vm_stats_timestamp = None _vm_stats = {} uid = None def __init__(self, name, groups, credit=0, credit_timestamp='', uid=None, balance_limit=0): self.__name__ = name self.groups = groups self.credit = credit self.balance_limit = balance_limit self._credit_timestamp = credit_timestamp if credit_timestamp else self._credit_timestamp self.uid = uid self._vm_stats = {} self._vm_stats_timestamp = None def get_name(self): return self.__name__ def set_name(self, value): self.__name__ = value name = property(get_name, set_name) @property def credit_timestamp(self): return self._credit_timestamp def set_credit(self, value): if type(value) in (int, long): self._credit = value elif type(value) is float: self._credit = int(value * 100) else: raise ValueError('credit must be integer or float!') self._credit_timestamp = datetime.now().isoformat() def get_credit(self): return self._credit credit = property(get_credit, set_credit) def set_vm_stats(self, stats): self._vm_stats = stats self._vm_stats_timestamp = datetime.now().isoformat() def get_vm_stats(self): return self._vm_stats vm_stats = property(get_vm_stats, set_vm_stats) @property def vm_stats_timestamp(self): return self._vm_stats_timestamp def set_balance_limit(self, value): if type(value) in (int, long): self._balance_limit = value elif type(value) is float: self._balance_limit = int(value * 100) else: raise ValueError('balance limit must be integer or float!') def get_balance_limit(self): return self._balance_limit balance_limit = property(get_balance_limit, set_balance_limit) def has_credit(self): return self.credit > 0 - self.balance_limit def display_name(self): return self.name def __repr__(self): return "UserProfile('%s', %s, %s, %s, '%s', %s)" % ( self.__name__, self.groups, self.credit, self.balance_limit, self.credit_timestamp, self.uid)
class Compute(Container): """A compute node.""" implements(ICompute, IDisplayName, IMarkable, IInVirtualizationContainer) permissions(dict(hostname=('read', 'modify'), mac_addr=('read', 'modify'), ipv4_address=('read', 'zope.Security'), ipv6_address=('read', 'modify'), nameservers=('read', 'modify'), dns_domains=('read', 'modify'), architecture=('read', 'modify'), cpu_info=('read', 'modify'), os_release=('read', 'modify'), kernel=('read', 'modify'), state=('read', 'modify'), effective_state=('read', 'modify'), num_cores=('read', 'modify'), memory=('read', 'modify'), diskspace=('read', 'modify'), network=('read', 'modify'), uptime=('read', 'modify'), swap_size=('read', 'modify'), cpu_usage=('read'), memory_usage=('read'), diskspace_usage=('read'), network_usage=('read'), cpu_limit=('read', 'modify'), template=('read', 'modify'), autostart=('read', 'modify'), ctid=('read', 'modify'), exclude_from_allocation=('read', 'modify'), license_activated=('read', 'zope.Security') )) __contains__ = IInCompute __markers__ = [IVirtualCompute, IDeployed, IUndeployed, IDeploying, IZabbixConfiguration, IManageable, ISaltInstalled, IFuncInstalled, IAllocating] hostname = u'' mac_address = None _ipv4_address = u'0.0.0.0/32' ipv6_address = u'::/128' nameservers = [u'8.8.8.8'] dns_domains = [] architecture = (u'x86_64', u'linux', u'centos') cpu_info = u"unknown" os_release = u"build 35" kernel = u"unknown" last_ping = False pingcheck = [] suspicious = False failure = False num_cores = 1 memory = 2048, network = 12.5 * M # bytes diskspace = { u'total': 2000.0, u'/': 500.0, u'/boot': 100.0, u'/storage': 1000.0, } swap_size = 4192 # empty values for metrics uptime = None cpu_usage = (0.0, 0.0, 0.0) memory_usage = 0.0 network_usage = (0.0, 0.0) diskspace_usage = { u'root': 0.0, u'boot': 0.0, u'storage': 0.0, } cpu_limit = 1.0 autostart = False # zabbix specific zabbix_hostgroups = [] zabbix_dns_name = None zabbix_ipv4_address = None zabbix_use_dns = True zabbix_agent_port = 10050 agent_version = u'' exclude_from_allocation = False license_activated = True notify_admin = False def __init__(self, hostname, state=None, memory=None, template=None, ipv4_address=None, mgt_stack=None): super(Compute, self).__init__() self.hostname = hostname self.memory = memory self.state = state self.template = template if ipv4_address: self._ipv4_address = ipv4_address self._mgt_stack = mgt_stack if self.template: alsoProvides(self, IVirtualCompute) alsoProvides(self, IUndeployed) elif self._mgt_stack: alsoProvides(self, self._mgt_stack) assert self.hostname def display_name(self): return self.hostname.encode('utf-8') @property def nicknames(self): """Returns all the nicknames of this Compute instance. Nicknames can be used to traverse to this object using alternative, potentially more convenient and/more memorable, names. """ return [self.hostname, ] @property def effective_state(self): """Since we lack schema/data upgrade scripts I have to resort on this tricks to cope with the fact that I have existing objects around in the several test dbs, and branches. """ return getattr(self, '_effective_state', unicode(self.state)) def get_ctid(self): return getattr(self, '_ctid', None) def set_ctid(self, value): self._ctid = int(value) if value is not None else None ctid = property(get_ctid, set_ctid) def __str__(self): return 'compute%s' % self.__name__ def get_consoles(self): if 'consoles' not in self._items: self._add(Consoles()) return self._items['consoles'] def set_consoles(self, value): if 'consoles' in self._items: del self._items['consoles'] self._add(value) consoles = property(get_consoles, set_consoles) @property def templates(self): from opennode.oms.zodb import db @db.assert_transact def do_it(): if not self['templates']: templates = Templates() templates.__name__ = 'templates' self._add(templates) return self['templates'] return do_it() def get_interfaces(self): if 'interfaces' not in self._items: self._add(NetworkInterfaces()) return self._items['interfaces'] def set_interfaces(self, value): if 'interfaces' in self._items: del self._items['interfaces'] self._add(value) interfaces = property(get_interfaces, set_interfaces) def get_routes(self): if 'routes' not in self._items: self._add(NetworkRoutes()) return self._items['routes'] def set_routes(self, value): if 'routes' in self._items: del self._items['routes'] self._add(value) routes = property(get_routes, set_routes) def get_ipv4_address(self): if 'interfaces' not in self._items: return self._ipv4_address primaries = [i.ipv4_address for i in self._items['interfaces'] if i.ipv4_address and getattr(i, 'primary', False)] if primaries: return unicode(primaries[0]) # No interface has been marked as primary, so let's just pick one addresses = [i.ipv4_address for i in self._items['interfaces'] if i.ipv4_address] if not addresses: return self._ipv4_address return unicode(addresses[0]) @require_admins def set_ipv4_address_fallback(self, value): """ Sets the fallback value of the IP address """ self._ipv4_address = value ipv4_address = property(get_ipv4_address, set_ipv4_address_fallback) def __repr__(self): return '<Compute %s>' % self.__name__ def set_owner(self, principal): super(Compute, self).set_owner(principal) log.info('%s changed owner to: %s', self.__name__, principal)
class ReadonlyContainer(Model): """A container whose items cannot be modified, i.e. are predefined.""" implements(IContainer) permissions( dict( listnames='traverse', listcontent='traverse', __iter__='traverse', __getitem__='traverse', can_contain='add', content='traverse', add='add', )) def __getitem__(self, key): return self.content().get(key) def listnames(self): return self.content().keys() def listcontent(self): return self.content().values() def __iter__(self): return iter(self.listcontent()) def can_contain(self, item): """A read only container cannot accept new children""" return False @exception_logger def content(self): injectors = querySubscriptions(self, IContainerInjector) for injector in injectors: interface_filter = getattr(injector, '__interfaces__', []) if interface_filter and not any( map(lambda i: i.providedBy(self), interface_filter)): continue for k, v in injector.inject().items(): if k not in self._items: v.__parent__ = self self._items[k] = v items = dict(**self._items) extenders = querySubscriptions(self, IContainerExtender) for extender in extenders: interface_filter = getattr(extender, '__interfaces__', []) if interface_filter and not any( map(lambda i: i.providedBy(self), interface_filter)): continue children = extender.extend() for v in children.values(): v.__parent__ = self v.__transient__ = True v.inherit_permissions = True items.update(children) return items _items = {}
class Model(persistent.Persistent): implements(IModel, IAttributeAnnotatable, ITimestamp) permissions(dict(__name__='view')) __parent__ = None __name__ = None __transient__ = False _inherit_permissions = False _ctime = None _mtime = None _mtime_blacklist = ('inherit_permissions', 'owner', 'features', 'oid', 'metadata') def __init__(self, *args, **kwargs): self._ctime = self._mtime = time.time() super(Model, self).__init__(self, *args, **kwargs) @property def ctime(self): if self._ctime is None: self._ctime = time.time() return self._ctime @property def mtime(self): if self._mtime is None: self._mtime = time.time() return self._mtime def _p_resolveConflict(self, oldState, savedState, newState): logger.debug('Resolve conflict: %s -> %s -> %s, choosing last', oldState, savedState, newState) return newState def set_inherit_permissions(self, value): self._inherit_permissions = value def get_inherit_permissions(self): return self._inherit_permissions or self.__transient__ inherit_permissions = property(get_inherit_permissions, set_inherit_permissions) def set_owner(self, principal): prinrole = interfaces.IPrincipalRoleManager(self) oldowner = self.__owner__ prinrole.unsetRoleForPrincipal('owner', oldowner) prinrole.assignRoleToPrincipal('owner', principal.id) if (not hasattr(self, '__suppress_events') and principal is not None and principal.id != oldowner): handle(self, OwnerChangedEvent(oldowner, principal.id)) def get_owner(self): prinrole = interfaces.IPrincipalRoleManager(self) owners = prinrole.getPrincipalsForRole('owner') owners = map(lambda p: p[0], filter(lambda p: p[1].getName() == 'Allow', owners)) assert len( owners ) <= 1, 'There must only be one owner, got %s instead' % owners if len(owners) == 1: return owners[0] __owner__ = property(get_owner, set_owner) @classmethod def class_implemented_interfaces(cls): return get_direct_interfaces(cls) def implemented_interfaces(self): return self.class_implemented_interfaces() + list( directlyProvidedBy(self).interfaces()) @classmethod def get_class_features(cls): return set([i.__name__ for i in cls.class_implemented_interfaces()]) def get_features(self): return set([i.__name__ for i in self.implemented_interfaces()]) def set_features(self, values): """ Features is a pseudo attribute which allows us to treat marker interfaces as if they were attributes. This special setter behaves like the tags setter, allowing addition and removal of individual marker interfaces from omsh. """ # we have to reset the object otherwise indexing framework # won't update removed values features = set(self.get_features()) def marker_by_name(name): for i in getattr(self, '__markers__', []): if i.__name__ == name: return i return None if not any(i.startswith('-') or i.startswith('+') for i in values): for i in getattr(self, '__markers__', []): noLongerProvides(self, i) # ignore empty strings for value in (i for i in values if i): op = value[0] if value[0] in ['-', '+'] else None if op: value = value[1:] marker = marker_by_name(value) if marker: if op == '-': if value in features: noLongerProvides(self, marker) else: alsoProvides(self, marker) features = property(get_features, set_features) def __setattr__(self, name, value): super(Model, self).__setattr__(name, value) if not name.startswith('_') and name not in self._mtime_blacklist: # useful debug info, but very verbose #logger.debug('setattr: %s: %s' % (self, name)) self._mtime = time.time()