Giter VIP home page Giter VIP logo

python-libmaas's Introduction

python-libmaas

Python client API library made especially for MAAS.

CI tests codecov.io

Installation

All the dependencies are declared in setup.py so this can be installed with pip. Python 3.5+ is required.

When working from master it can be helpful to use a virtualenv:

$ python3 -m venv ve && source ve/bin/activate
$ pip install git+https://github.com/canonical/python-libmaas.git
$ maas --help

Releases are periodically made to PyPI but, at least for now, it makes more sense to work directly from trunk.

Documentation

Documentation can be generated with make docs which publishes into the site directory. Recent documentation is also published to the MAAS Client Library & CLI documentation site.

Development

It's pretty easy to start hacking on python-libmaas:

$ git clone [email protected]:maas/python-libmaas.git
$ cd python-libmaas
$ make develop
$ make test

Installing IPython is generally a good idea too:

$ bin/pip install -UI IPython

Pull requests are welcome but authors need to sign the Canonical contributor license agreement before those PRs can be merged.

History & licence

In short: AGPLv3.

python-libmaas was begun by a core MAAS developer, Gavin Panella, on his own time, but is now maintained by the core MAAS team at Canonical. It is licensed under the GNU Affero GPLv3, the same as MAAS itself.

Some of the code in here has come from MAAS, upon which Canonical Ltd has the copyright. Gavin Panella licenses his parts under the AGPLv3, and MAAS is also under the AGPLv3, so everything should be good.

python-libmaas's People

Contributors

albertodonato avatar allenap avatar benoitknecht avatar bjornt avatar blakerouse avatar brendan-donegan avatar canozyurt avatar costya-y avatar dmascialino avatar fabianbaier avatar garymm avatar jhobbs avatar juan-vg avatar kakkotetsu avatar ltrager avatar lutostag avatar martinstrycek avatar mi-alkhamis avatar mkinney avatar mpontillo avatar newell avatar pontillo avatar r00ta avatar roaksoax avatar sabaini avatar sk1y101 avatar skatsaounis avatar sparkiegeek avatar troyanov avatar yan0s avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-libmaas's Issues

Transition CI from CLI to Python-LibMAAS

The intention long term is for python-libmaas to be the first-class API for interacting with MAAS. Therefore we want to switch the existing CI from using CLI commands to using python-libmaas directly. In order to achieve this, python-libmaas will need to support at least the subset of operations required by the CI.

Ability to power node on/off

I noticed that it is pretty direct to get the power parameters, but I don't see a clean way to power a node off/on. What is the best way with the current code to power a node off or on?

Unable to switch profiles

Trying to switch between multiple maas profiles is failing. A sqlite error is falling through ๐Ÿ‘

# "switching" to a different existing profile breaks
Tue.11:27  jblackwell@work~$ maas profiles switch kafka-sac1
Error: UNIQUE constraint failed: index 'only_one_profile_selected'

~$ which maas
/usr/local/bin/maas
Tue.11:30  jblackwell@work
~$ head -n 1 /usr/local/bin/maas
#!/usr/local/opt/python3/bin/python3.6
Tue.11:31  jblackwell@work

~$ python3.6 --version
Python 3.6.5
Tue.11:31  jblackwell@work
~$ pip3.6 list | grep maas
DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
python-libmaas (0.5.0)

TypeError: Unions cannot be used with issubclass()

Following the documentation I ran into this error: TypeError: Unions cannot be used with issubclass().

I created the environment on my Mac with conda: conda create --name galaxy python=3.5
Switched into the env and installed via: pip install git+https://github.com/maas/python-libmaas.git
Until here everything was successful. When I tried to start maas --help I get:

Traceback (most recent call last):
  File "/Users/fabianbaier/anaconda/envs/galaxy/bin/maas", line 11, in <module>
    load_entry_point('python-libmaas==0.3.1', 'console_scripts', 'maas')()
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/site-packages/setuptools-27.2.0-py3.5.egg/pkg_resources/__init__.py", line 565, in load_entry_point
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/site-packages/setuptools-27.2.0-py3.5.egg/pkg_resources/__init__.py", line 2598, in load_entry_point
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/site-packages/setuptools-27.2.0-py3.5.egg/pkg_resources/__init__.py", line 2258, in load
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/site-packages/setuptools-27.2.0-py3.5.egg/pkg_resources/__init__.py", line 2264, in resolve
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/site-packages/maas/client/flesh/__init__.py", line 31, in <module>
    from .. import (
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/site-packages/maas/client/bones/__init__.py", line 22, in <module>
    from . import helpers
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/site-packages/maas/client/bones/helpers.py", line 28, in <module>
    from ..utils.profiles import Profile
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/site-packages/maas/client/utils/profiles.py", line 24, in <module>
    from .types import JSONObject
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/site-packages/maas/client/utils/types.py", line 30, in <module>
    assert issubclass(str, JSONValue)
  File "/Users/fabianbaier/anaconda/envs/galaxy/lib/python3.5/typing.py", line 770, in __subclasscheck__
    raise TypeError("Unions cannot be used with issubclass().")
TypeError: Unions cannot be used with issubclass().```

Add methods to transition to/from Rescue mode for Machines

To facilitate the transition of the CI from using the CLI to using libmaas, we need to add methods on the Machine objects to:

  • Enter rescue mode
  • Exit rescue mode

This might be harder than it looks as we might want to take this opportunity to wrap the inherently asynchronous nature of this operation, i.e. does this asynchronous operation end when the command has been issued, or when the machine is actually in/out of rescue mode?

Can't delete nodes/machines

Environment

python-libmaas==0.6.1
Python 3.6.7

Problem

As stated in the docs a node/machine should have the method delete(). Instead, when you call it, you will get the error AttributeError: 'Machine' object has no attribute 'delete'

Cant save controller interfaces

In [1]: from maas.client import connect

In [2]: maas = connect('http://10.48.0.230:5240/MAAS', apikey='***')                        

In [3]: region = maas.region_controllers.list()[0]                             

In [4]: region.interfaces[0].save()    
---------------------------------------------------------------------------    
TypeError                                 Traceback (most recent call last)    
<ipython-input-5-b9ffffab3c42> in <module>()                                   
----> 1 region.interfaces[0].save()    

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/utils/async.py in wrapper(*args, **kwargs)                                                          
     47         if not eventloop.is_running():                                 
     48             while isawaitable(result):                                 
---> 49                 result = eventloop.run_until_complete(result)          
     50         return result          
     51                                

/usr/lib/python3.6/asyncio/base_events.py in run_until_complete(self, future)  
    465             raise RuntimeError('Event loop stopped before Future completed.')                                                                          
    466                                
--> 467         return future.result() 
    468                                
    469     def stop(self):            

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/viscera/interfaces.py in save(self)                                                                 
    132             del self._changed_data['tags']                             
    133         self._changed_data.update(                                     
--> 134             calculate_dict_diff(self._orig_data['params'], self.params))                                                                               
    135         if 'vlan' in self._changed_data and self._changed_data['vlan']:
    136             # Update uses the ID of the VLAN, not the VLAN object.     

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/viscera/__init__.py in __getattribute__(self, name)                                                 
    345         if name in fields:     
    346             if self.loaded:    
--> 347                 return super(Object, self).__getattribute__(name)      
    348             elif is_pk_descriptor(fields[name], include_alt=True):     
    349                 return super(Object, self).__getattribute__(name)      

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/viscera/__init__.py in __get__(self, instance, owner)                                               
    746             if self.name in instance._data:                            
    747                 datum = instance._data[self.name]                      
--> 748                 return self.datum_to_value(instance, datum)            
    749             elif self.default is undefined:                            
    750                 raise AttributeError(self.name)                        

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/viscera/__init__.py in datum_to_value_method(instance, datum)                                       
    664             @wraps(datum_to_value)                                     
    665             def datum_to_value_method(instance, datum):                
--> 666                 return datum_to_value(datum)                           
    667             attrs["datum_to_value"] = staticmethod(datum_to_value_method)                                                                              
    668         if value_to_datum is not None:                                 

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/viscera/__init__.py in checker(value)                                                               
   1054         else:                  
   1055             raise TypeError(   
-> 1056                 "%r is not of type %s" % (value, expected))            
   1057     return checker             
   1058                                

TypeError: '' is not of type <class 'dict'>       

This happens without changing anything. When I change something on the interface, my intention I get the same traceback.

ImportError: No module named 'aiohttp.errors'

Looks like in version 2.0.0 aiohttp dropped aiohttp.errors: https://media.readthedocs.org/pdf/aiohttp/2.0.0/aiohttp.pdf

When I try to load the library I get:

File "/Users/fabianbaier/anaconda/envs/libmaas/lib/python3.5/site-packages/maas/client/bones/__init__.py", line 19, in <module>
    import aiohttp.errors
ImportError: No module named 'aiohttp.errors'

pip freeze shows aiohttp==2.0.0 - as a work around I installed aiohttp==1.3.3 which produced no import error.

Machines/Machine classes need to be updated to use new terminology

I'm not sure whether it's planned to support both 1.0 and 2.0 API versions, but it looks like several of the APIs need updating to use 2.0 terminology. For example the Machines class provides an 'acquire' class method but in 2.0 it's referred to as 'allocate'. Again, the Machine class provides a method 'start' but this is referred to as 'deploy' in 2.0

vlans are not correctly dehydrated

In [2]: from maas.client import connect

In [3]: maas = connect('http://10.48.0.230:5240/MAAS', apikey='***')                        

In [4]: other = maas.subnets.list()[0] 

In [5]: other.vlan = other.vlan        

In [6]: other.save()                   
---------------------------------------------------------------------------    
AssertionError                            Traceback (most recent call last)    
<ipython-input-6-01f21911bae3> in <module>()                                   
----> 1 other.save()                   

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/utils/async.py in wrapper(*args, **kwargs)                                                          
     47         if not eventloop.is_running():                                 
     48             while isawaitable(result):                                 
---> 49                 result = eventloop.run_until_complete(result)          
     50         return result          
     51                                

/usr/lib/python3.6/asyncio/base_events.py in run_until_complete(self, future)  
    465             raise RuntimeError('Event loop stopped before Future completed.')                                                                          
    466                                
--> 467         return future.result() 
    468                                
    469     def stop(self):            

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/viscera/__init__.py in save(self)                                                                   
    480                     for key in self._handler.params                    
    481                 })             
--> 482                 self._data = await self._handler.update(**update_data) 
    483         else:                  
    484             raise AttributeError(                                      

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/bones/__init__.py in __call__(self, **data)                                                         
    300             if key.startswith('_'):                                    
    301                 data[key[1:]] = data.pop(key)                          
--> 302         response = await self.bind(**params).call(**data)              
    303         return response.data   
    304                                

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/bones/__init__.py in call(self, **data)                                                             
    388         :param data: Data to pass in the *body* of the request.        
    389         """                    
--> 390         uri, body, headers = self.prepare(data)                        
    391         return self.dispatch(uri, body, headers)                       
    392                                

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/bones/__init__.py in prepare(self, data)                                                            
    418         # Bundle things up ready to throw over the wire.               
    419         uri, body, headers = utils.prepare_payload(                    
--> 420             self.action.op, self.action.method, self.uri, data)        
    421                                
    422         # Headers are returned as a list, but they must be a dict for  

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/utils/__init__.py in prepare_payload(op, method, uri, data)                                         
    109         # Even if data is empty, construct a multipart request body. Piston                                                                            
    110         # (server-side) sets `request.data` to `None` if there's no payload.                                                                           
--> 111         message = build_multipart_message(data)                        
    112         headers, body = encode_multipart_message(message)              
    113                                

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/utils/multipart.py in build_multipart_message(data)                                                 
    122     message = MIMEMultipart("form-data")                               
    123     for name, content in data: 
--> 124         for payload in make_payloads(name, content):                   
    125             message.attach(payload)                                    
    126     return message             

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/utils/multipart.py in make_payloads(name, content)                                                  
    112     elif isinstance(content, Iterable):                                
    113         for part in content:   
--> 114             for payload in make_payloads(name, part):                  
    115                 yield payload  
    116     else:                      

~/.virtualenvs/mmm/lib/python3.6/site-packages/maas/client/utils/multipart.py in make_payloads(name, content)                                                  
    116     else:                      
    117         raise AssertionError(  
--> 118             "%r is unrecognised: %r" % (name, content))                
    119                                
    120                                

AssertionError: 'vlan' is unrecognised: <Fabric id=0 (unloaded)>               

In [7]: 

This is just a small repro. I am obviously trying to set it to a different vlan, this is just the most concise repro I could get.

Subnets have no fabric attribute

Environment

python-libmaas==0.6.1
Python 3.6.7

Problem

The fabric associated to a subnet can't be retrieved. There is a workaround:

  1. retrieve the vlan
  2. get the fabric that the vlan has

How it should be

The subnets have a fabric associated to them. It should be possible to retrieve it as an attribute of the subnet

Machine status_ attributes throw AttributeError: sub<attribute_name>

After getting Machines from the origin, if I try to access the status_ attributes, I get an exception like:

machines[0].status_name
Traceback (most recent call last):
File "", line 1, in
File "/home/brendand/src/alburnum-maas-client/alburnum/maas/viscera/init.py", line 378, in get
raise AttributeError(self.name)
AttributeError: substatus_name

Accessing machines[0].status returns fine, as does any other attribute (even when it includes an underscore)

relay_vlans cannot be set with a vlan object or int id

While trying to wrap setting a vlan's relay_vlan attribute I was not able to accomplish this with the latest python-libmaas code.

If I use an in (vid or vlan.id): I get this error:

2018-05-23-17:28:17 DEBUG Setting vlan:  - relay_vlan to 2733
value type: <class 'int'>
value = 2733
Traceback (most recent call last):
  File "foundation/bin/maas-config-networks", line 333, in <module>
    sys.exit(main())
  File "foundation/bin/maas-config-networks", line 324, in main
    fabric_vlans=fabric_vlans)
  File "foundation/bin/maas-config-networks", line 242, in apply_vlans_to_fabric
    set_vlan_attr(vlan, attr.lower(), value)
  File "foundation/bin/maas-config-networks", line 222, in set_vlan_attr
    setattr(vlan, attr, value)
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/viscera/__init__.py", line 363, in __setattr__
    ret = super(Object, self).__setattr__(name, value)
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/viscera/__init__.py", line 759, in __set__
    datum = self.value_to_datum(instance, value)
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/viscera/__init__.py", line 888, in value_to_datum
    "must be %s, not %s" % (self.cls, type(value).__name__))
TypeError: must be Vlan, not int
Makefile:106: recipe for target 'networkconfig' failed
make: *** [networkconfig] Error 1

When I try to set the relay_vlan to a vlan object, I get this error:

2018-05-23-17:23:30 DEBUG Setting vlan:  - relay_vlan to Vlan
value type: <class 'origin.Vlan'>
value = Vlan
Traceback (most recent call last):
  File "foundation/bin/maas-config-networks", line 333, in <module>
    sys.exit(main())
  File "foundation/bin/maas-config-networks", line 324, in main
    fabric_vlans=fabric_vlans)
  File "foundation/bin/maas-config-networks", line 242, in apply_vlans_to_fabric
    set_vlan_attr(vlan, attr.lower(), value)
  File "foundation/bin/maas-config-networks", line 223, in set_vlan_attr
    vlan.save()
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/utils/async.py", line 49, in wrapper
    result = eventloop.run_until_complete(result)
  File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
    return future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/viscera/vlans.py", line 108, in save
    self._data = await self._handler.update(**update_data)
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/bones/__init__.py", line 302, in __call__
    response = await self.bind(**params).call(**data)
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/bones/__init__.py", line 390, in call
    uri, body, headers = self.prepare(data)
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/bones/__init__.py", line 420, in prepare
    self.action.op, self.action.method, self.uri, data)
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/utils/__init__.py", line 111, in prepare_payload
    message = build_multipart_message(data)
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/utils/multipart.py", line 124, in build_multipart_message
    for payload in make_payloads(name, content):
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/utils/multipart.py", line 114, in make_payloads
    for payload in make_payloads(name, part):
  File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/utils/multipart.py", line 118, in make_payloads
    "%r is unrecognised: %r" % (name, content))
AssertionError: 'relay_vlan' is unrecognised: <Fabric id=3 (unloaded)>
Makefile:106: recipe for target 'networkconfig' failed

orign.xxxx problems - NameError: name 'origin' is not defined

Hi team,

There seems to be problems with viscera and bones. We can list users, machines and devices with no problem, but when I try to get the version we get the following:

nexius@ubuntu:~$ maas shell
Welcome to the MAAS shell.
Predefined objects:
client:
A pre-canned client for 'rootpro'.
In [1]: origin.Version.read()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-22b2f32223e9> in <module>()
----> 1 origin.Version.read()
NameError: name 'origin' is not defined

We followed carefully the instructions in the guide. So we logged in again but we only get the

A pre-canned client for 'rootpro'.

but never the:

Predefined variables:
origin: A viscera origin, configured for foo.
session: A bones session, configured for foo.

I tried also to get logged in programmatically and we get the same result (with bones and viscera):

Viscera:
In [2]: profile, origin = Origin.login("http://maas-rc-vm:5240/MAAS/api/2.0/", username="xxx",password="xxx")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-2-476daac84867> in <module>() ----> 1 profile, origin = Origin.login("http://maas-rc-vm:5240/MAAS/api/2.0/", username="xxx",password="xxx")
NameError: name 'Origin' is not defined

Bones:
In [3]: profile, session = bones.SessionAPI.login("http://maas-rc-vm:5240/MAAS/api/2.0/", username="root",password="nexlan13")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-f5899c9dc824> in <module>() ----> 1 profile, session = bones.SessionAPI.login("http://maas-rc-vm:5240/MAAS/api/2.0/", username="xxx",password="xxx")
NameError: name 'bones' is not defined

We installed it via PyPI (pip install python-libmaas) and we have the latest version. This is what was installed with pip:

Requirement already up-to-date: python-libmaas in /usr/local/lib/python3.5/dist-packages
Requirement already up-to-date: terminaltables>=2.1.0 in /usr/local/lib/python3.5/dist-packages (from python-libmaas)
Requirement already up-to-date: beautifulsoup4>=4.4.1 in /usr/local/lib/python3.5/dist-packages (from python-libmaas)
Requirement already up-to-date: oauthlib>=1.0.3 in /usr/local/lib/python3.5/dist-packages (from python-libmaas)
Requirement already up-to-date: aiohttp>=1.1.4 in /usr/local/lib/python3.5/dist-packages (from python-libmaas)
Requirement already up-to-date: colorclass>=1.2.0 in /usr/local/lib/python3.5/dist-packages (from python-libmaas)
Requirement already up-to-date: PyYAML>=3.11 in /usr/local/lib/python3.5/dist-packages (from python-libmaas)
Requirement already up-to-date: pytz>=2014.10 in /usr/local/lib/python3.5/dist-packages (from python-libmaas)
Requirement already up-to-date: argcomplete>=1.0 in /usr/local/lib/python3.5/dist-packages (from python-libmaas)
Requirement already up-to-date: async-timeout>=1.1.0 in /usr/local/lib/python3.5/dist-packages (from aiohttp>=1.1.4->python-libmaas)
Requirement already up-to-date: multidict>=2.1.4 in /usr/local/lib/python3.5/dist-packages (from aiohttp>=1.1.4->python-libmaas)
Requirement already up-to-date: yarl<0.10,>=0.9.8 in /usr/local/lib/python3.5/dist-packages (from aiohttp>=1.1.4->python-libmaas)
Requirement already up-to-date: chardet in /usr/lib/python3/dist-packages (from aiohttp>=1.1.4-python-libmaas)

Could it be possible that libmaas is not complete? Which libraries should we have for this to work?

maas client does not obey ssl

Using the following example based on the one provided by the manual
(please pay attention to the httpS )

from maas.client import login
client = login(
    "https://localhost:5240/MAAS/",
    username="my_user", password="my_pass",
)
tmpl = "{0.hostname} {1.name} {1.mac_address}"
for machine in client.machines.list():
    for interface in machine.interfaces:
        print(tmpl.format(machine, interface))

If MAAS is accessible via https only, the client will be able to successfuly connect/login, but subsequent commands will fail as a url without s (http-only) is used.

machines.list() is incredibly slow

On maas 2.5.2 It took 40 seconds to load on localhost (for about 100 nodes)

The performance is way too bad, I can imagine the total nodes could easily go beyond 10k in production. That basically means load forever.

The query should support something like filter by ip, and the backend service need some improvement as well

Color codes appear in CLI output when they shouldn't

When I ran watch maas machines I see color codes in the output, such as:

Every 2.0s: maas machines                                Tue Oct 10 15:31:21 2017

+----------+-------+----------+-----------+-------+-------+---------+
| Hostname | Power | Status   | Owner     | Arch  | #CPUs | RAM     |
+----------+-------+----------+-----------+-------+-------+---------+
| nuc1     | Off   | ^[92mReady^[39m    | (none)    | amd64 | 4     | 8.0 GB  |
| nuc2     | Off   | ^[94mDeployed^[39m | mpontillo | amd64 | 2     | 8.0 GB  |
| nuc3     | Off   | ^[94mDeployed^[39m | mpontillo | amd64 | 4     | 8.0 GB  |
| skylake  | Off   | ^[94mDeployed^[39m | mpontillo | amd64 | 8     | 64.0 GB |
+----------+-------+----------+-----------+-------+-------+---------+

Can't add tags to nodes/machines

Environment

python-libmaas==0.6.1
Python 3.6.7

Problem

The node/machine attribute tags is readonly. It doesn't allow to manipulate those tags.

Proposed solution

The endpoint api/2.0/tags/<TAG>/?op=update_nodes allows to add/remove tags to/from nodes

PyPI version 0.6.1 does not match GH version 0.6.1

Howdy!

The package version in PyPI and GitHub are not the same, but have the same version number (0.6.1). See the following:

$ python3 -m virtualenv pypi
$ python3 -m virtualenv github
$ pypi/bin/pip install -q python-libmaas
$ github/bin/pip install -q git+https://github.com/maas/python-libmaas.git@585a85ac9b93156e074702de05c56761ed09b9b9
$ diff pypi/lib/python3.7/site-packages/maas/client/__init__.py github/lib/python3.7/site-packages/maas/client/__init__.py
8c8
< from .utils.async import asynchronous
---
> from .utils.maas_async import asynchronous

I would propose a version number bump - 0.6.1 -> 0.6.2, perhaps - to account for this.

Thanks!

Connect Function Not Working

I tried the below:

#!/usr/bin/env python3
from maas.client import connect
URL = 'http://192.168.2.1:5240/MAAS/'
KEY = 'Soop3r:S3cr4t:k3y3'
c = connect(URL,apikey=KEY,insecure=True)

When I run this code I get the below errors:

File "./round2.py", line 8, in <module>
    c = connect(URL,apikey=KEY,insecure=True)
  File "/usr/local/lib/python3.5/dist-packages/maas/client/utils/async.py", line 49, in wrapper
    result = eventloop.run_until_complete(result)
  File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
    return future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/usr/local/lib/python3.5/dist-packages/maas/client/__init__.py", line 25, in connect
    url, apikey=apikey, insecure=insecure)
  File "/usr/local/lib/python3.5/dist-packages/maas/client/viscera/__init__.py", line 615, in connect
    url=url, apikey=apikey, insecure=insecure)
  File "/usr/local/lib/python3.5/dist-packages/maas/client/bones/__init__.py", line 91, in connect
    url=url, apikey=apikey, insecure=insecure)
  File "/usr/local/lib/python3.5/dist-packages/maas/client/bones/helpers.py", line 112, in connect
    description = await fetch_api_description(url, credentials, insecure)
  File "/usr/local/lib/python3.5/dist-packages/maas/client/bones/helpers.py", line 47, in fetch_api_description
    async with session, session.get(url_describe) as response:
AttributeError: __aexit__
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7f82aa41d860>

Looks like I can't even get to step 1 ... connecting

What is the secret sauce to connect?

Cannot create new ip range

This client code:
new_range = client.ip_ranges.create(ip_rng_attrs['start_ip'], ip_rng_attrs['end_ip'])

Is generating this error:
Traceback (most recent call last):
File "foundation/bin/maas-config-networks", line 290, in
sys.exit(main())
File "foundation/bin/maas-config-networks", line 285, in main
resolve_vlans(**params)
File "foundation/bin/maas-config-networks", line 205, in resolve_vlans
apply_vlan_attr(attr, value)
File "foundation/bin/maas-config-networks", line 187, in apply_vlan_attr
end_ip=ip_rng_attrs['end_ip'])
File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/utils/async.py", line 49, in wrapper
result = eventloop.run_until_complete(result)
File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
return future.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
raise self._exception
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/viscera/ipranges.py", line 69, in create
return cls._object(await cls._handler.create(**params))
File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/bones/init.py", line 302, in call
response = await self.bind(**params).call(**data)
File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/bones/init.py", line 390, in call
uri, body, headers = self.prepare(data)
File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/bones/init.py", line 420, in prepare
self.action.op, self.action.method, self.uri, data)
File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/utils/init.py", line 111, in prepare_payload
message = build_multipart_message(data)
File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/utils/multipart.py", line 124, in build_multipart_message
for payload in make_payloads(name, content):
File "/home/ubuntu/cpe-deployments/libmaas-venv/lib/python3.5/site-packages/maas/client/utils/multipart.py", line 118, in make_payloads
"%r is unrecognised: %r" % (name, content))
AssertionError: 'type' is unrecognised: <IPRangeType.RESERVED: 'reserved'>
Makefile:105: recipe for target 'networkconfig' failed
make: *** [networkconfig] Error 1

It was my understanding that 'type' is optional and not required, therefore this is happening with default value.

ssh command does not work when ICMP echo requests are filtered

I used sshuttle -r <server> <cidr> to access a remote MAAS and then tried maas ssh <server> to access a deployed machine.

It hangs while trying to determine the best IP address, due to the use of ping to try to determine which IP address is available. This is because sshuttle is not able to forward ICMP packets to remote hosts; it only forwards TCP traffic.

In this case, ping fails with Destination Port Unreachable. If ping is not able to be used, it would be nice to fall back to another mechanism. Possibly using something like nc to test if the SSH port is open would be more reliable in cases like these.

[featurerequest] Ability to query power information

It would be really useful to be able to use the "op=power_parameters" machine query to get IPMI information. Something like...

c.machines.get('machineid').power_parameters

I looked through the code to see if I could add it myself but used up my self-imposed timebox :) The code uses some abstractions that make it pretty difficult to follow for someone new to the project.

Machine.commission testing_scripts parameter not consistent with API documentation

As per API documentation (https://docs.maas.io/2.4/en/api), the testing_scripts parameter should be : "A comma seperated list of testing script names and tags to be run. By default all tests tagged 'commissioning' will be run. Set to 'none' to disable running tests."

In the Machine class commission function, it mentions "Passing empty list will disable running any testing scripts during commissioning."

Also the parameter validation at the begining of the function does it

if testing_scripts is not None:
	if len(testing_scripts) == 0:
		params["testing_scripts"] = ""
	else:
		params["testing_scripts"] = ",".join(testing_scripts)

However, when MaaS receives an empty 'testing_scripts' parameter, it does return HTTP 400 with this error:
{"testing_scripts": ["Select a valid choice. is not one of the available choices."], "all": ["Commission is not available because of the current state of the node."]}

The workaround I found was to pass testing_scripts=["none"] to the commission function.

RuntimeError: coroutine raised StopIteration

I got an error at login phase: RuntimeError: coroutine raised StopIteration and i cannot find why.

I use libmaas in a virtualenv using the example:
pip install git+https://github.com/maas/python-libmaas.git

The code is pretty simple, and target a remote MAAS through a ssh port forwarding tunnel

#!/usr/bin/env python3.5

from maas.client import login
client = login(
    "http://localhost:5555/MAAS/",
    username="xxxx", password="xxxx",
)

Here is the output:

(amc) user@myhost:~โŸซ python3 maas_client.py 
Traceback (most recent call last):
  File "/home/user/amc/lib/python3.5/site-packages/maas/client/bones/helpers.py", line 261, in _obtain_token
    cookie for cookie in session.cookie_jar
StopIteration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "maas_client.py", line 7, in <module>
    username="xxxx", password="xxxx",
  File "/home/user/amc/lib/python3.5/site-packages/maas/client/utils/async.py", line 49, in wrapper
    result = eventloop.run_until_complete(result)
  File "/usr/lib/python3.5/asyncio/base_events.py", line 457, in run_until_complete
    return future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 292, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/home/user/amc/lib/python3.5/site-packages/maas/client/__init__.py", line 43, in login
    url, username=username, password=password, insecure=insecure)
  File "/home/user/amc/lib/python3.5/site-packages/maas/client/viscera/__init__.py", line 603, in login
    url=url, username=username, password=password, insecure=insecure)
  File "/home/user/amc/lib/python3.5/site-packages/maas/client/bones/__init__.py", line 75, in login
    url=url, username=username, password=password, insecure=insecure)
  File "/home/user/amc/lib/python3.5/site-packages/maas/client/bones/helpers.py", line 199, in login
    url.geturl(), username, password, insecure=insecure)
RuntimeError: coroutine raised StopIteration

Here is the lib versions:

(amc) user@myhost:~โŸซ pip freeze
aiohttp==1.3.5
appdirs==1.4.3
argcomplete==1.8.2
async-timeout==1.2.0
beautifulsoup4==4.5.3
chardet==2.3.0
colorclass==2.2.0
multidict==2.1.4
oauthlib==2.0.1
packaging==16.8
pkg-resources==0.0.0
pyparsing==2.2.0
python-libmaas==0.4.1
pytz==2016.10
PyYAML==3.12
six==1.10.0
terminaltables==3.1.0
yarl==0.9.8

Thanks for your help

SSH keys endpoint

In order to facilitate the transition of the MAAS CI tests from CLI commands to python-libmaas, we need to add support for SSH keys to the libmaas API. Currently, required operations are:

  • List all SSH keys that MAAS knows about
  • Create a new SSH key

VLAN endpoint for MAAS CI

We want to be able to use the VLAN endpoint in the MAAS CI. The required operations are:

  • Update a specified VLAN
  • Delete a specified VLAN

HandlerAPI Missing 'new'

client.tags.create("foo")

/usr/local/lib/python3.5/site-packages/maas/client/viscera/tags.py in create(cls, name, comment, definition, kernel_opts)
     20
     21     async def create(cls, name, *, comment="", definition="", kernel_opts=""):
---> 22         data = await cls._handler.new(
     23             name=name, comment=comment, definition=definition,
     24             kernel_opts=kernel_opts)

AttributeError: 'HandlerAPI' object has no attribute 'new'

Looks like there's no new method here:

https://github.com/maas/python-libmaas/blob/95e849456fa500bca32790fd781cba3fdf831071/maas/client/bones/__init__.py#L148

Abitilty to edit boot device

Hi,

Could the library grow the ability to change the boot device of a node ? As far as I can see, it'd need to implement the "blockdevice" / "blockdevice_set" objects.

For what it's worth, I'm currently doing that with :
maas $MAAS_PROFILE block-device set-boot-disk $system_id $blockdev_id

Thanks !

maas deploy should accept full hostname

I found a node in the web UI and tried to deploy to it:

$ maas deploy xenial node04.maaslab
Error: Unable to find machine node04.maaslab.

It works if I specify only node04, though, which is kind of nice. But it should accept the name we display in the web UI as well.

client.login only works with when endpoint is a hostname and not an IP address

Log-in doesn't work with IP addresses, it only works with hostnames.

client = login("http://10.10.10.10:5240/MAAS/", username="user", password="user")
Traceback (most recent call last):
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/bones/helpers.py", line 249, in _obtain_token
cookie for cookie in session.cookie_jar
StopIteration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "", line 1, in
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/utils/async.py", line 49, in wrapper
result = eventloop.run_until_complete(result)
File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
return future.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
raise self._exception
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/init.py", line 43, in login
url, username=username, password=password, insecure=insecure)
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/viscera/init.py", line 603, in login
url=url, username=username, password=password, insecure=insecure)
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/bones/init.py", line 76, in login
url=url, username=username, password=password, insecure=insecure)
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/bones/helpers.py", line 187, in login
url.geturl(), username, password, insecure=insecure)
RuntimeError: coroutine raised StopIteration

client = login("http://192.168.10.27:5240/MAAS/", username="admin", password="admin")
Traceback (most recent call last):
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/bones/helpers.py", line 249, in _obtain_token
cookie for cookie in session.cookie_jar
StopIteration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "", line 1, in
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/utils/async.py", line 49, in wrapper
result = eventloop.run_until_complete(result)
File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
return future.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
raise self._exception
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/init.py", line 43, in login
url, username=username, password=password, insecure=insecure)
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/viscera/init.py", line 603, in login
url=url, username=username, password=password, insecure=insecure)
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/bones/init.py", line 76, in login
url=url, username=username, password=password, insecure=insecure)
File "/home/ubuntu/amc/lib/python3.5/site-packages/maas/client/bones/helpers.py", line 187, in login
url.geturl(), username, password, insecure=insecure)
RuntimeError: coroutine raised StopIteration

[Python missing modules]No module named maas - No module named apiclient

Hi,

I have been trying to run python-maas from a remote server to reach the Rack-Controller through the API so I can get some information, but nothing seems to work. I tried the examples under the documentation and every time I find that I have missing modules:

Trying to run the example in docs- index-An example directly in Pythoon prompt

from maas.client import login
Traceback (most recent call last):
File "", line 1, in
ImportError: No module named 'maas'

Trying to run an example from stackoverflow

Traceback (most recent call last):
File "./maas-py-client.py", line 8, in
from apiclient import maas_client
ImportError: No module named 'apiclient'

Tryng to run as an script (obviously same error as the first one - tried this one after creating a new VM):

(amc) ubuntu@ubuntu:~$ ./maas-test-python.py
Traceback (most recent call last):
File "./maas-test-python.py", line 3, in
from maas.client import login
ImportError: No module named 'maas'

I have installed as per the instructions:
$ virtualenv --python=python3.5 amc && source amc/bin/activate
$ pip install git+https://github.com/maas/python-libmaas.git
$ maas --help

I get the maas client working. But I guess that since there are some problems in the python libraries I can't get logged in with specifique api keys. Just as Anonymous and of course I can't access any command. This are the errors:

(amc) ubuntu@ubuntu:~$ maas profiles list
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Profile name โ”‚ URL โ”‚ Anonymous? โ”‚ Default?โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ nexius-test โ”‚ http:///MAAS/api/2.0/ โ”‚ Yes โ”‚ โœ“ โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€_____โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜

maasprofiles login <profile> http://<IP>:5240/MAAS/api/2.0/ <apikey> Password:
Error: coroutine raised StopIteration

Since I am with the anonymous user I can't get into any command:
maas list-users
Error: 'NoneType' object has no attribute 'read'

I am using ubuntu 16.04.
I am not sure if I am missing something (most likely) or if there is other branch I should be using? Because I tried in 3 different VMs and it is not working. The same missing modules.
Can you help me?

`maas login` doesn't prompt for username/password

blake@blake-ubnt-laptop:~/Code/python-libmaas$ bin/maas login
URL: http://192.168.122.2:5240/MAAS/
Error: Login failed: Forbidden

It should prompt for the username and password before trying to request the authorization token. In the regiond.log only 1 HTTP request is made.

2018-05-02 08:54:06 regiond: [info] 192.168.122.1 POST /MAAS/api/2.0/account/?op=create_authorisation_token HTTP/1.1 --> 401 UNAUTHORIZED (referrer: -; agent: python-requests/2.18.4)

Add vlans to facade

Please add the vlans back to facades, so that we can create a vlan. There is no way to create a vlan on a fabric without exporting that as a facade. Will file a PR to fix.

machines.get_power_parameters should not be top level on machines

We are creating this library to make it easy for people to use the MAAS API. Placing this operation at the top level doesn't seem like the best idea or present a clean library for people to use. I would think something like this would be better:

machine = await client.machines.get("asdasd")
power_parameters = await machine.get_power_parameters()

Getting the power parameters for all the nodes at the same time seems like a weird operation to want. If we want to have the top level one as well that is fine, but I think the main way and the documented way should really be, what is above.

Unable to update power params

using "machine.power_type = 'manual'" gives me "AttributeError: power_type is read-only"
using "machine.update(...)" gives me "AttributeError: 'Machine' object has no attribute 'update'"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.