restructure osmclient
[osm/osmclient.git] / osmclient / v1 / package.py
1 # Copyright 2017 Sandvine
2 #
3 # All Rights Reserved.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
6 # not use this file except in compliance with the License. You may obtain
7 # a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
16
17 """
18 OSM package API handling
19 """
20
21 import json
22 import pycurl
23 from io import BytesIO
24 import tarfile
25 import re
26 import yaml
27 import time
28 from osmclient.common.exceptions import ClientException
29 from osmclient.common.exceptions import NotFound
30 from osmclient.common import utils
31
32
33 class Package(object):
34 def __init__(self,http=None,upload_http=None,client=None):
35 self._client=client
36 self._http=http
37 self._upload_http=upload_http
38
39 def _wait_for_package(self,pkg_type):
40 if 'vnfd' in pkg_type['type']:
41 get_method=self._client.vnfd.get
42 elif 'nsd' in pkg_type['type']:
43 get_method=self._client.nsd.get
44 else:
45 raise ClientException("no valid package type found")
46
47 # helper method to check if pkg exists
48 def check_exists( func ):
49 try:
50 func()
51 except NotFound:
52 return False
53 return True
54
55 return utils.wait_for_value(lambda: check_exists(lambda: get_method(pkg_type['name'])))
56
57 # method opens up a package and finds the name of the resulting
58 # descriptor (vnfd or nsd name)
59 def get_descriptor_type_from_pkg(self, descriptor_file):
60 tar = tarfile.open(descriptor_file)
61 yamlfile = None
62 for member in tar.getmembers():
63 if re.match('.*.yaml',member.name) and len(member.name.split('/')) == 2:
64 yamlfile = member.name
65 break
66 if yamlfile is None:
67 return None
68
69 dict=yaml.load(tar.extractfile(yamlfile))
70 result={}
71 for k1,v1 in dict.items():
72 if not k1.endswith('-catalog'):
73 continue
74 for k2,v2 in v1.items():
75 if not k2.endswith('nsd') and not k2.endswith('vnfd'):
76 continue
77
78 if 'nsd' in k2:
79 result['type'] = 'nsd'
80 else:
81 result['type'] = 'vnfd'
82
83 for entry in v2:
84 for k3,v3 in entry.items():
85 if k3 == 'name' or k3.endswith(':name'):
86 result['name'] = v3
87 return result
88 tar.close()
89 return None
90
91 def wait_for_upload(self,filename):
92 """wait(block) for an upload to succeed.
93
94 The filename passed is assumed to be a descriptor tarball.
95 """
96 pkg_type=self.get_descriptor_type_from_pkg(filename)
97
98 if pkg_type is None:
99 raise ClientException("Cannot determine package type")
100
101 if not self._wait_for_package(pkg_type):
102 raise ClientException("package {} failed to upload".format(filename))
103
104 def upload(self,filename):
105 resp=self._upload_http.post_cmd(formfile=('package',filename))
106 if not resp or 'transaction_id' not in resp:
107 raise ClientException("failed to upload package")