如何使用murano的PL语言

    xiaoxiao2021-03-25  69

    声明: 本博客欢迎转载,但请保留原作者信息! 作者:柯晓东 团队:华为杭州OpenStack团队

    最近在用Murano来部署应用,关于Murano包及PL语言的使用,这里总结一下,便于后来者。

    先说Murano包,典型的Murano包如下图所示。含有UI的称为Application,它能继承library,但是不能被其他Application继承了。library不含UI,一般是平台提供,里面含有丰富的公共方法和属性。

    UI目录 下放能自动生成表单的yaml文件。Murano之所以好用,是因为含有用文本描述的UI,以此可以在新接入一个组件时UI的活由新组件提供,非常适合平台和服务解耦。Murano通过yaml描述的UI也不是什么都能体现。指定某个输入框一定要输入字符串或一定要有值,这它是能做到的。但是下面这种场景它做不到:某radio button的值,为A时,几个输入框必须输入;为B时,同样的几个输入框可以不输入。 UI支持数字、字符串、布尔型,是否必选等基本类型,还支持通过glance、neutron选择镜像、虚拟网络,但是不支持选择物理主机。它支持的类型如下:

    类型说明stringDjango 字符串类型booleanDjango 布尔类型textDjango 文本类型integerDjango 数字类型password秘密类型clusterip集群IPfloatingip外网Ipdomain域名table表格flavor规格keypair密钥对image镜像azoneavailability zoomimageType仅为镜像提供的属性

    Resource目录 下放的是各式各样的脚本,这部分基本都和服务的实现有关。例如运行态的动态配置脚本,数据转换脚本等。

    Classes目录 下放的是核心的yaml描述的部署文件。这些yaml就是用murano PL语言描述的类。这是这次介绍的核心部分。 Murano PL的类分为这么几部分: 1. 类名声明 2. 继承声明 3. 属性声明 4. 方法实现 前两部分和其他语言一样,就略过了。

    在属性声明的地方,主要涉及给变量起了名字后,要写什么类型,作用范围。如下图是典型的属性声明的代码段: 这里的Contract表示类型声明,下表是所有可用的类型:

    类型说明$.int()整形$.string()字符串$.string().notNull()非空字符串$.bool()布尔类型(true/false) 0会被转为false,其他转为true$.class(ns:ClassName)类$.class(ns:ClassName).notNull()非空类$.class(ns:Name).check($.p = 12)类,并且含有名为p的属性,且值为12$.template(ns:ClassName)模板声明,一般用于脚本调用使用[$.int()]数组[$.int().notNull()]数组[$.string()]数组[$.int().check($ > 0)]正数的数组[$.int(), 2]数组长度至少为2[$.int(), 2, 5]数组长度至少为2,至多为5{ A: $.int(), B: [$.string()] }字典,key是int,value是字符串

    Usage是用来声明作用域,可填的值如下:

    属性类型说明In输入参数,该参数只能通过UI设置,不能在MuranoPL代码里面修改。这是类属性的默认类型。Out输出参数,该参数只能在MuranoPL代码里面修改,不能通过UI设置。InOut既能由UI设置,又能在MuranoPL代码修改的参数。Const和In类似,不同的是只能被用户设置一次。Runtime和Out类似,不同的是不会被序列化。

    然后就来到方法实现,Murano PL是一种用python解释的类yaml的语言,它有如下的约束: 1. 赋值用冒号,且冒号后要跟空格 2. 等号表示判断 3. 逗号不能在字符串内使用 4. 变量要用$作为前缀 5. 单个$ 就是java里面的this,而$xxx 表示变量xxx,$.xxx 表示类变量xxx

    基本的代码片段如下: (1) if语句

    - If: not $.getAttr(deployed, false) Then: - $.setAttr(deployed, true) Else: - $._environment.reporter.report($, "application has deployed")

    (2) for循环

    - For: applicationPort In: $applicationPorts.where($.scope != host) Do: - $._environment.reporter.report($, 'Configuring etcd node {0}'.format($applicationPort))

    (3) while循环

    - $port: 1025 - While: not $._checkIfPortIsNotUsed($port, $protocol) Do: $port: $port + 1

    (4) 并发执行(可指定并发数)

    - Parallel: - $.node1.deployInstance() - $.node2.deployInstance() - $.node3.deployInstance() - $.node4.deployInstance() - $.node5.deployInstance() - $.node6.deployInstance() - Limit: 2

    (5) switch语句

    Switch: $predicate1(): - code - block $predicate2(): - code - block Default: - code - block

    (6)异常处理

    Try: - code - block Catch: With: keyError As: e Do: - code - block Else: - code - block Finally: - code - block

    (7)调用脚本

    - $resources: new(sys:Resources) - $template: $resources.yaml('DeployOrionChef.template').bind(dict( port => $.port)) - $result: $.instance.agent.call($template, $resources)

    (8)方法定义

    getTitle: Body: - Return: $.title checkIfPortUsed: Arguments: - port: Contract: $.int().notNull() - protocol: Contract: $.string().notNull() Body: - Return: len(list($.serviceEndpoints.where($.port = $port).where($.protocol = $protocol))) = 0

    常用的公共方法 如下:

    方法说明sleep(5)暂停5秒now().year获取当前年份id(xxx)取类实例的idsuper(xxx)取类实例的父类xxx.name获取组件名typeinfo(xxx)获取实例类型typeinfo(xxx).type获取类名typeinfo(xxx).version获取版本typeinfo(xxx).package获取包typeinfo(xxx).ancestors获取类的父类typeinfo(xxx).properties获取类所有属性。并可通过typeinfo(xxx).properties[i].getValue(xxx) 获取xxx对象的第i个属性的值typeinfo(xxx).methods获取类所有方法,并可通过typeinfo(xxx).methods[i].invoke(xxx, ‘bar’, 2) 调用xxx对象第i个方法

    常用的数组方法如下:

    方法描述[0, 1, 2].first()取数组的第一个元素[0, 1, 2].last()取数组的最后一个元素[0, 1, 2].len()查询数组长度range(5).toList()产生0到4的数组dict(a => 1, b => 2)定义字典[1, 2, 3].append(4, 5)数组相加{“a” => 1, “b” => 2}.items()字典转数组[1, 2, 3, 4, 5].where($ > 3)取数组第3位开始的子集isList([1, 2])判断是否是列表isInteger(12.0)判断是否是整数isNumber(12)判断是否数字max(8, 2)取两者大者min(8, 2)取两者小者

    常用的字符串方法如下:

    方法描述str(123)数字转字符串isString(1)判断是否是字符串concat(“abc”, “de”, “f”)多个字符串合并[“abc”, “de”, “f”].join(“|”)多个字符串合并“|”.join([“abc”, “de”, “f”])多个字符串合并“abc”.len()字符串长度“aB1c”.toUpper()转大写“AB1c”.toLower()转小写“abc de f”.split()分割字符串” abcd “.trim()去掉前后空格“abaab”.replace(“ab”, “cd”)替换字符串“abc{foo}ab{bar}abc”.format(foo => ” “, bar => “,”)用参数填充字符串“cabcdab”.indexOf(“ab”, 2)从前往后查关键字“cabcdab”.lastIndexOf(“ab”)从后往前查关键字“abc de”.toCharArray()字符串转数组“abcd”.startsWith(“ab”, “xx”)是否以特定字符串开头“abcd”.endsWith(“cd”, “xx”)是否以特定字符串结尾

    在预定义的基础公共类(core-library)中,最重要的是environment和instance。他们分别代表着运行环境和虚拟机对象。这两个类的常用属性如下: (1) 环境(std:Environment)的属性

    属性描述默认类型name名字InapplicationsUI界面上能够显示出来的Application的列表。如果是new出来的对象,不在这个列表内。InagentListener和Murano Agent通信的属性, io.murano.system.AgentListenerRuntimestack和Heat交互用,常用的操作有current()、push()、updateTemplate($template)、setTemplate($template)RuntimeinstanceNotifier获取部署实例时信息的类, io.murano.system.InstanceNotifierRuntimedefaultNetworks网络信息(io.murano.resources.Network).InsecurityGroupManager安全组信息Runtime

    (2) 实例(res:Instance)的属性

    属性描述默认类型namenova的实例名Inflavornova的套餐Inimageglance的景象Inkeynamenova的keypairInagent和Murano Agent通信的属性io.murano.system.Agent.RuntimeipAddressesIP地址列表的数组,如果有浮动IP,放置在列表末尾Outnetworks虚拟机使用的网络Involumes虚拟机使用的卷信息InblockDevices如果从卷启动,需要指定(Volume class, device name, device type, boot order)InassignFloatingIp是否需要指定浮动ip,默认False.InfloatingIpAddress浮动ip地址OutsecurityGroupName安全组名In

    其余还想知道的,可参看手册:http://murano.readthedocs.io/en/stable-liberty/appdev-guide/murano_pl.html

    附1:用devstack在ubuntu安装murano。 (1)下载devstack git clone https://git.openstack.org/openstack-dev/devstack (2)配置apt-get使用阿里云的源(/etc/apt/sources.list)

    deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse ##测试版源 deb http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse # 源码 deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse ##测试版源 deb-src http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse

    (3)在devstack目录新建local.conf

    [[local|localrc]] LOGFILE=stack.sh.log LOG_COLOR=False DATABASE_PASSWORD=stack RABBIT_PASSWORD=stack SERVICE_TOKEN=stack SERVICE_PASSWORD=stack ADMIN_PASSWORD=stack disable_service n-net enable_service q-svc enable_service q-agt enable_service q-dhcp enable_service q-l3 enable_service q-meta enable_service q-lbaas enable_service q-vpn Q_PLUGIN=ml2 ENABLE_TENANT_VLANS=True IP_VERSION=4 GIT_BASE=https://github.com IMAGE_URLS=http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img # Enable Horizon disable_service tempest enable_service horizon # Enable Heat enable_service heat h-api h-api-cfn h-api-cw h-eng # Enable Murano enable_plugin murano https://git.openstack.org/openstack/murano enable_service murano murano-api murano-engine

    (4)在devstack目录下,运行stack.sh安装murano 附2:murano PL调试方法 murano会在 /tmp/murano-package-cache目录下,为已经上传的包弄缓存。通过直接修改该目录下的文件,可以免除重新上传包的麻烦动作,改之后直接在UI上测试即可。

    转载请注明原文地址: https://ju.6miu.com/read-32868.html

    最新回复(0)